blob: bc87c8e7dfa803c19d8a48cdfb35a0bba5899433 [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"
Michael Wrightd02c5b62014-02-10 15:10:22 -080019
Cody Heiner166a5af2023-07-07 12:25:00 -070020#include <NotifyArgsBuilders.h>
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 Pradhanaeebeb42023-06-13 19:53:03 +000098static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000099static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000100
Antonio Kantek15beb512022-06-13 22:35:41 +0000101// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000102static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000103static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000104
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000105// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000106static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000107
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 {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000209 struct AnrResult {
210 sp<IBinder> token{};
211 gui::Pid pid{gui::Pid::INVALID};
212 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800213
Michael Wrightd02c5b62014-02-10 15:10:22 -0800214public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000215 FakeInputDispatcherPolicy() = default;
216 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800217
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800218 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700219 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700220 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700221 EXPECT_EQ(event.getDisplayId(), args.displayId);
222
223 const auto& keyEvent = static_cast<const KeyEvent&>(event);
224 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
225 EXPECT_EQ(keyEvent.getAction(), args.action);
226 });
Jackal Guof9696682018-10-05 12:23:23 +0800227 }
228
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700229 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
230 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700231 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700232 EXPECT_EQ(event.getDisplayId(), args.displayId);
233
234 const auto& motionEvent = static_cast<const MotionEvent&>(event);
235 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
236 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000237 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
240 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700241 });
Jackal Guof9696682018-10-05 12:23:23 +0800242 }
243
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700244 void assertFilterInputEventWasNotCalled() {
245 std::scoped_lock lock(mLock);
246 ASSERT_EQ(nullptr, mFilteredEvent);
247 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800248
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800249 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700250 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800251 ASSERT_TRUE(mConfigurationChangedTime)
252 << "Timed out waiting for configuration changed call";
253 ASSERT_EQ(*mConfigurationChangedTime, when);
254 mConfigurationChangedTime = std::nullopt;
255 }
256
257 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700258 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800259 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800260 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800261 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
262 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
263 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
264 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
265 mLastNotifySwitch = std::nullopt;
266 }
267
chaviwfd6d3512019-03-25 13:23:49 -0700268 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800270 ASSERT_EQ(touchedToken, mOnPointerDownToken);
271 mOnPointerDownToken.clear();
272 }
273
274 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700275 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800276 ASSERT_TRUE(mOnPointerDownToken == nullptr)
277 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700278 }
279
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700280 // This function must be called soon after the expected ANR timer starts,
281 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500282 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700283 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800285 std::unique_lock lock(mLock);
286 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500287 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 ASSERT_NO_FATAL_FAILURE(
289 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500290 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700291 }
292
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000293 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800294 const sp<WindowInfoHandle>& window) {
295 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
296 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
297 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500298 }
299
Prabir Pradhanedd96402022-02-15 01:46:16 -0800300 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
301 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000302 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800303 std::unique_lock lock(mLock);
304 android::base::ScopedLockAssertion assumeLocked(mLock);
305 AnrResult result;
306 ASSERT_NO_FATAL_FAILURE(result =
307 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000308 ASSERT_EQ(expectedToken, result.token);
309 ASSERT_EQ(expectedPid, result.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,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000322 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800323 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));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000328 ASSERT_EQ(expectedToken, result.token);
329 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800330 }
331
332 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000333 sp<IBinder> getResponsiveWindowToken() {
334 std::unique_lock lock(mLock);
335 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800336 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
337 const auto& [token, _] = result;
338 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700339 }
340
341 void assertNotifyAnrWasNotCalled() {
342 std::scoped_lock lock(mLock);
343 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800344 ASSERT_TRUE(mAnrWindows.empty());
345 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500346 << "ANR was not called, but please also consume the 'connection is responsive' "
347 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700348 }
349
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000350 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800351 std::unique_lock lock(mLock);
352 base::ScopedLockAssertion assumeLocked(mLock);
353
354 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
355 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000356 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800357 enabled;
358 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000359 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
360 << ") to be called.";
361 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800362 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000363 auto request = *mPointerCaptureRequest;
364 mPointerCaptureRequest.reset();
365 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800366 }
367
368 void assertSetPointerCaptureNotCalled() {
369 std::unique_lock lock(mLock);
370 base::ScopedLockAssertion assumeLocked(mLock);
371
372 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000373 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800374 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000375 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800376 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000377 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800378 }
379
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700380 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
381 const sp<IBinder>& targetToken) {
382 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800383 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800384 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800385 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800386 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800387 }
388
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800389 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
390 std::unique_lock lock(mLock);
391 base::ScopedLockAssertion assumeLocked(mLock);
392 std::optional<sp<IBinder>> receivedToken =
393 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
394 mNotifyInputChannelBroken);
395 ASSERT_TRUE(receivedToken.has_value());
396 ASSERT_EQ(token, *receivedToken);
397 }
398
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800399 /**
400 * Set policy timeout. A value of zero means next key will not be intercepted.
401 */
402 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
403 mInterceptKeyTimeout = timeout;
404 }
405
Josep del Riob3981622023-04-18 15:49:45 +0000406 void assertUserActivityPoked() {
407 std::scoped_lock lock(mLock);
408 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
409 }
410
411 void assertUserActivityNotPoked() {
412 std::scoped_lock lock(mLock);
413 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
414 }
415
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000416 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000417 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
418 }
419
420 void assertNotifyDeviceInteractionWasNotCalled() {
421 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
422 }
423
Michael Wrightd02c5b62014-02-10 15:10:22 -0800424private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700425 std::mutex mLock;
426 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
427 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
428 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
429 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800430
Prabir Pradhan99987712020-11-10 18:43:05 -0800431 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000432
433 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800434
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700435 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700436 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800437 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
438 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700439 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800440 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
441 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700442
arthurhungf452d0b2021-01-06 00:19:52 +0800443 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800444 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000445 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800446
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800447 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
448
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000449 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000450
Prabir Pradhanedd96402022-02-15 01:46:16 -0800451 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
452 // for a specific container to become non-empty. When the container is non-empty, return the
453 // first entry from the container and erase it.
454 template <class T>
455 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
456 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
457 // If there is an ANR, Dispatcher won't be idle because there are still events
458 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
459 // before checking if ANR was called.
460 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
461 // to provide it some time to act. 100ms seems reasonable.
462 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
463 const std::chrono::time_point start = std::chrono::steady_clock::now();
464 std::optional<T> token =
465 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
466 if (!token.has_value()) {
467 ADD_FAILURE() << "Did not receive the ANR callback";
468 return {};
469 }
470
471 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
472 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
473 // the dispatcher started counting before this function was called
474 if (std::chrono::abs(timeout - waited) > 100ms) {
475 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
476 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
477 << "ms, but waited "
478 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
479 << "ms instead";
480 }
481 return *token;
482 }
483
484 template <class T>
485 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
486 std::queue<T>& storage,
487 std::unique_lock<std::mutex>& lock,
488 std::condition_variable& condition)
489 REQUIRES(mLock) {
490 condition.wait_for(lock, timeout,
491 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
492 if (storage.empty()) {
493 ADD_FAILURE() << "Did not receive the expected callback";
494 return std::nullopt;
495 }
496 T item = storage.front();
497 storage.pop();
498 return std::make_optional(item);
499 }
500
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600501 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700502 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800503 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000506 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800507 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700508 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800509 ASSERT_TRUE(pid.has_value());
510 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700511 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500512 }
513
Prabir Pradhanedd96402022-02-15 01:46:16 -0800514 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000515 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500516 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800517 ASSERT_TRUE(pid.has_value());
518 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500519 mNotifyAnr.notify_all();
520 }
521
522 void notifyNoFocusedWindowAnr(
523 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
524 std::scoped_lock lock(mLock);
525 mAnrApplications.push(applicationHandle);
526 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800527 }
528
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800529 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
530 std::scoped_lock lock(mLock);
531 mBrokenInputChannels.push(connectionToken);
532 mNotifyInputChannelBroken.notify_all();
533 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800534
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600535 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700536
Chris Yef59a2f42020-10-16 12:55:26 -0700537 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
538 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
539 const std::vector<float>& values) override {}
540
541 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
542 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000543
Chris Yefb552902021-02-03 17:18:37 -0800544 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
545
Prabir Pradhana41d2442023-04-20 21:30:40 +0000546 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700547 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000548 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700549 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000550 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
551 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800552 break;
553 }
554
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700555 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000556 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
557 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800558 break;
559 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700560 default: {
561 ADD_FAILURE() << "Should only filter keys or motions";
562 break;
563 }
Jackal Guof9696682018-10-05 12:23:23 +0800564 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565 return true;
566 }
567
Prabir Pradhana41d2442023-04-20 21:30:40 +0000568 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
569 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800570 // Clear intercept state when we handled the event.
571 mInterceptKeyTimeout = 0ms;
572 }
573 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600575 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576
Prabir Pradhana41d2442023-04-20 21:30:40 +0000577 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800578 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
579 // Clear intercept state so we could dispatch the event in next wake.
580 mInterceptKeyTimeout = 0ms;
581 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582 }
583
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
585 uint32_t) override {
586 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587 }
588
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600589 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
590 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700591 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800592 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
593 * essentially a passthrough for notifySwitch.
594 */
Harry Cutts33476232023-01-30 19:57:29 +0000595 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800596 }
597
Josep del Riob3981622023-04-18 15:49:45 +0000598 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
599 std::scoped_lock lock(mLock);
600 mPokedUserActivity = true;
601 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600603 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700604 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700605 mOnPointerDownToken = newToken;
606 }
607
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000608 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800609 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000610 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800611 mPointerCaptureChangedCondition.notify_all();
612 }
613
arthurhungf452d0b2021-01-06 00:19:52 +0800614 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
615 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800616 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800617 mDropTargetWindowToken = token;
618 }
619
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000620 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000621 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000622 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
623 }
624
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700625 void assertFilterInputEventWasCalledInternal(
626 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700627 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800628 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700629 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800630 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800631 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632};
633
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634// --- InputDispatcherTest ---
635
636class InputDispatcherTest : public testing::Test {
637protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000641 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000642 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
643 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000644 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000645 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700646 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800647 }
648
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000649 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700650 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000651 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700652 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700654
655 /**
656 * Used for debugging when writing the test
657 */
658 void dumpDispatcherState() {
659 std::string dump;
660 mDispatcher->dump(dump);
661 std::stringstream ss(dump);
662 std::string to;
663
664 while (std::getline(ss, to, '\n')) {
665 ALOGE("%s", to.c_str());
666 }
667 }
Vishnu Nair958da932020-08-21 17:12:37 -0700668
Chavi Weingarten847e8512023-03-29 00:26:09 +0000669 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700670 FocusRequest request;
671 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000672 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700673 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
674 request.displayId = window->getInfo()->displayId;
675 mDispatcher->setFocusedWindow(request);
676 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677};
678
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
680 KeyEvent event;
681
682 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800683 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
684 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000685 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600686 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800687 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000688 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000689 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 << "Should reject key events with undefined action.";
691
692 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
694 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600695 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000697 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 << "Should reject key events with ACTION_MULTIPLE.";
700}
701
702TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
703 MotionEvent event;
704 PointerProperties pointerProperties[MAX_POINTERS + 1];
705 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800706 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800707 pointerProperties[i].clear();
708 pointerProperties[i].id = i;
709 pointerCoords[i].clear();
710 }
711
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800712 // Some constants commonly used below
713 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
714 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
715 constexpr int32_t metaState = AMETA_NONE;
716 constexpr MotionClassification classification = MotionClassification::NONE;
717
chaviw9eaa22c2020-07-01 16:21:27 -0700718 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800719 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700722 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700723 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
724 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000725 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800726 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000727 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000728 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800729 << "Should reject motion events with undefined action.";
730
731 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800732 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800733 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
734 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
735 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
736 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000737 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000739 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000740 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800741 << "Should reject motion events with pointer down index too large.";
742
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700744 AMOTION_EVENT_ACTION_POINTER_DOWN |
745 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700746 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
747 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700748 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with pointer down index too small.";
754
755 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800757 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
758 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
759 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
760 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with pointer up index too large.";
766
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700768 AMOTION_EVENT_ACTION_POINTER_UP |
769 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700770 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer up index too small.";
778
779 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
781 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
784 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with 0 pointers.";
790
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with more than MAX_POINTERS pointers.";
801
802 // Rejects motion events with invalid pointer ids.
803 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800804 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
805 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700806 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700807 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
808 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000809 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000811 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000812 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800813 << "Should reject motion events with pointer ids less than 0.";
814
815 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
826
827 // Rejects motion events with duplicate pointer ids.
828 pointerProperties[0].id = 1;
829 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800830 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
831 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700832 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700833 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
834 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000835 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000838 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800839 << "Should reject motion events with duplicate pointer ids.";
840}
841
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
843
844TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
845 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000846 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800847 ASSERT_TRUE(mDispatcher->waitForIdle());
848
849 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
850}
851
852TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000853 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
854 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000855 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800856
857 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
858 args.policyFlags |= POLICY_FLAG_TRUSTED;
859 mFakePolicy->assertNotifySwitchWasCalled(args);
860}
861
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700862namespace {
863
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700864static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700865// Default input dispatching timeout if there is no focused application or paused window
866// from which to determine an appropriate dispatching timeout.
867static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
868 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
869 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800870
871class FakeApplicationHandle : public InputApplicationHandle {
872public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 FakeApplicationHandle() {
874 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700875 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500876 mInfo.dispatchingTimeoutMillis =
877 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700878 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800879 virtual ~FakeApplicationHandle() {}
880
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000881 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500883 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
884 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800886};
887
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800888class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800889public:
Garfield Tan15601662020-09-22 15:32:38 -0700890 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800891 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700892 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800893 }
894
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800895 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 InputEvent* event;
897 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
898 if (!consumeSeq) {
899 return nullptr;
900 }
901 finishEvent(*consumeSeq);
902 return event;
903 }
904
905 /**
906 * Receive an event without acknowledging it.
907 * Return the sequence number that could later be used to send finished signal.
908 */
909 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800910 uint32_t consumeSeq;
911 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800912
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800913 std::chrono::time_point start = std::chrono::steady_clock::now();
914 status_t status = WOULD_BLOCK;
915 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000916 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800917 &event);
918 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
919 if (elapsed > 100ms) {
920 break;
921 }
922 }
923
924 if (status == WOULD_BLOCK) {
925 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700926 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800927 }
928
929 if (status != OK) {
930 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800932 }
933 if (event == nullptr) {
934 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700935 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800936 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700937 if (outEvent != nullptr) {
938 *outEvent = event;
939 }
940 return consumeSeq;
941 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800942
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700943 /**
944 * To be used together with "receiveEvent" to complete the consumption of an event.
945 */
946 void finishEvent(uint32_t consumeSeq) {
947 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
948 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800949 }
950
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000951 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
952 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
953 ASSERT_EQ(OK, status);
954 }
955
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700956 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000957 std::optional<int32_t> expectedDisplayId,
958 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800959 InputEvent* event = consume();
960
961 ASSERT_NE(nullptr, event) << mName.c_str()
962 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800963 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
965 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800966
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000967 if (expectedDisplayId.has_value()) {
968 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970
Tiger Huang8664f8c2018-10-11 19:14:35 +0800971 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800973 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
974 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000975 if (expectedFlags.has_value()) {
976 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
977 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800978 break;
979 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800981 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000982 assertMotionAction(expectedAction, motionEvent.getAction());
983
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000984 if (expectedFlags.has_value()) {
985 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
986 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 break;
988 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
991 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700992 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800993 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
994 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700995 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000996 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
997 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800999 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1000 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001001 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001002 }
1003
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001004 MotionEvent* consumeMotion() {
1005 InputEvent* event = consume();
1006
1007 if (event == nullptr) {
1008 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1009 return nullptr;
1010 }
1011
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 if (event->getType() != InputEventType::MOTION) {
1013 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001014 return nullptr;
1015 }
1016 return static_cast<MotionEvent*>(event);
1017 }
1018
1019 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1020 MotionEvent* motionEvent = consumeMotion();
1021 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1022 ASSERT_THAT(*motionEvent, matcher);
1023 }
1024
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001025 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1026 InputEvent* event = consume();
1027 ASSERT_NE(nullptr, event) << mName.c_str()
1028 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001029 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1030 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001031
1032 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1033 << mName.c_str() << ": event displayId should always be NONE.";
1034
1035 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1036 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001037 }
1038
Prabir Pradhan99987712020-11-10 18:43:05 -08001039 void consumeCaptureEvent(bool hasCapture) {
1040 const InputEvent* event = consume();
1041 ASSERT_NE(nullptr, event) << mName.c_str()
1042 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1044 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001045
1046 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1047 << mName.c_str() << ": event displayId should always be NONE.";
1048
1049 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1050 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1051 }
1052
arthurhungb89ccb02020-12-30 16:19:01 +08001053 void consumeDragEvent(bool isExiting, float x, float y) {
1054 const InputEvent* event = consume();
1055 ASSERT_NE(nullptr, event) << mName.c_str()
1056 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001057 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001058
1059 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1060 << mName.c_str() << ": event displayId should always be NONE.";
1061
1062 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1063 EXPECT_EQ(isExiting, dragEvent.isExiting());
1064 EXPECT_EQ(x, dragEvent.getX());
1065 EXPECT_EQ(y, dragEvent.getY());
1066 }
1067
Antonio Kantekf16f2832021-09-28 04:39:20 +00001068 void consumeTouchModeEvent(bool inTouchMode) {
1069 const InputEvent* event = consume();
1070 ASSERT_NE(nullptr, event) << mName.c_str()
1071 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001072 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1073 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001074
1075 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1076 << mName.c_str() << ": event displayId should always be NONE.";
1077 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1078 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1079 }
1080
chaviwd1c23182019-12-20 18:44:56 -08001081 void assertNoEvents() {
1082 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001083 if (event == nullptr) {
1084 return;
1085 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001086 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001087 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1088 ADD_FAILURE() << "Received key event "
1089 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001090 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001091 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1092 ADD_FAILURE() << "Received motion event "
1093 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001094 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1096 ADD_FAILURE() << "Received focus event, hasFocus = "
1097 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001098 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001099 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1100 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1101 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001102 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001103 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1104 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1105 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001106 }
1107 FAIL() << mName.c_str()
1108 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001109 }
1110
1111 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1112
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001113 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1114
chaviwd1c23182019-12-20 18:44:56 -08001115protected:
1116 std::unique_ptr<InputConsumer> mConsumer;
1117 PreallocatedInputEventFactory mEventFactory;
1118
1119 std::string mName;
1120};
1121
chaviw3277faf2021-05-19 16:45:23 -05001122class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001123public:
1124 static const int32_t WIDTH = 600;
1125 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001126
Chris Yea209fde2020-07-22 13:54:51 -07001127 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001128 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001130 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001131 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001132 base::Result<std::unique_ptr<InputChannel>> channel =
1133 dispatcher->createInputChannel(name);
1134 token = (*channel)->getConnectionToken();
1135 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001136 }
1137
1138 inputApplicationHandle->updateInfo();
1139 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1140
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001141 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001142 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001143 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001145 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001146 mInfo.frameLeft = 0;
1147 mInfo.frameTop = 0;
1148 mInfo.frameRight = WIDTH;
1149 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001150 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001151 mInfo.globalScaleFactor = 1.0;
1152 mInfo.touchableRegion.clear();
1153 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001154 mInfo.ownerPid = WINDOW_PID;
1155 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001156 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001157 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001158 }
1159
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001160 sp<FakeWindowHandle> clone(int32_t displayId) {
1161 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1162 handle->mInfo = mInfo;
1163 handle->mInfo.displayId = displayId;
1164 handle->mInfo.id = sId++;
1165 handle->mInputReceiver = mInputReceiver;
1166 return handle;
1167 }
1168
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001169 void setTouchable(bool touchable) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1171 }
chaviwd1c23182019-12-20 18:44:56 -08001172
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001173 void setFocusable(bool focusable) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1175 }
1176
1177 void setVisible(bool visible) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1179 }
Vishnu Nair958da932020-08-21 17:12:37 -07001180
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001181 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001182 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001183 }
1184
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001185 void setPaused(bool paused) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1187 }
1188
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001189 void setPreventSplitting(bool preventSplitting) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001191 }
1192
1193 void setSlippery(bool slippery) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1195 }
1196
1197 void setWatchOutsideTouch(bool watchOutside) {
1198 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1199 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001200
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001201 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1202
1203 void setInterceptsStylus(bool interceptsStylus) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1205 }
1206
1207 void setDropInput(bool dropInput) {
1208 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1209 }
1210
1211 void setDropInputIfObscured(bool dropInputIfObscured) {
1212 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1213 }
1214
1215 void setNoInputChannel(bool noInputChannel) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1217 }
1218
Josep del Riob3981622023-04-18 15:49:45 +00001219 void setDisableUserActivity(bool disableUserActivity) {
1220 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1221 }
1222
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001223 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1224
chaviw3277faf2021-05-19 16:45:23 -05001225 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001226
Bernardo Rufino7393d172021-02-26 13:56:11 +00001227 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1228
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001229 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001230 mInfo.frameLeft = frame.left;
1231 mInfo.frameTop = frame.top;
1232 mInfo.frameRight = frame.right;
1233 mInfo.frameBottom = frame.bottom;
1234 mInfo.touchableRegion.clear();
1235 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001236
1237 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1238 ui::Transform translate;
1239 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1240 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001241 }
1242
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001243 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1244
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001245 void setIsWallpaper(bool isWallpaper) {
1246 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1247 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001248
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001249 void setDupTouchToWallpaper(bool hasWallpaper) {
1250 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1251 }
chaviwd1c23182019-12-20 18:44:56 -08001252
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001253 void setTrustedOverlay(bool trustedOverlay) {
1254 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1255 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001256
chaviw9eaa22c2020-07-01 16:21:27 -07001257 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1258 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1259 }
1260
1261 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001262
yunho.shinf4a80b82020-11-16 21:13:57 +09001263 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1264
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001265 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001266 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001267 }
1268
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001269 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001270 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001271 }
1272
Svet Ganov5d3bc372020-01-26 23:11:07 -08001273 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001274 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001275 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1276 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001277 }
1278
1279 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001280 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001281 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1282 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001283 }
1284
1285 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001287 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1288 }
1289
1290 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1291 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001292 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001293 expectedFlags);
1294 }
1295
Svet Ganov5d3bc372020-01-26 23:11:07 -08001296 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001297 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1298 int32_t expectedFlags = 0) {
1299 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1300 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001301 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001302 }
1303
1304 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001305 int32_t expectedFlags = 0) {
1306 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1307 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001308 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 }
1310
1311 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001313 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001314 expectedFlags);
1315 }
1316
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001317 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1318 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001319 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001320 expectedFlags);
1321 }
1322
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001323 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1324 int32_t expectedFlags = 0) {
1325 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001326 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001327 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001328 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1329 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1330 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1331 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1332 }
1333
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001334 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1335 ASSERT_NE(mInputReceiver, nullptr)
1336 << "Cannot consume events from a window with no receiver";
1337 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1338 }
1339
Prabir Pradhan99987712020-11-10 18:43:05 -08001340 void consumeCaptureEvent(bool hasCapture) {
1341 ASSERT_NE(mInputReceiver, nullptr)
1342 << "Cannot consume events from a window with no receiver";
1343 mInputReceiver->consumeCaptureEvent(hasCapture);
1344 }
1345
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001346 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1347 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001348 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001349 ASSERT_THAT(*motionEvent, matcher);
1350 }
1351
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001352 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001353 std::optional<int32_t> expectedDisplayId,
1354 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001355 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1356 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1357 expectedFlags);
1358 }
1359
arthurhungb89ccb02020-12-30 16:19:01 +08001360 void consumeDragEvent(bool isExiting, float x, float y) {
1361 mInputReceiver->consumeDragEvent(isExiting, x, y);
1362 }
1363
Antonio Kantekf16f2832021-09-28 04:39:20 +00001364 void consumeTouchModeEvent(bool inTouchMode) {
1365 ASSERT_NE(mInputReceiver, nullptr)
1366 << "Cannot consume events from a window with no receiver";
1367 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1368 }
1369
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001370 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001371 if (mInputReceiver == nullptr) {
1372 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1373 return std::nullopt;
1374 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001375 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001376 }
1377
1378 void finishEvent(uint32_t sequenceNum) {
1379 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1380 mInputReceiver->finishEvent(sequenceNum);
1381 }
1382
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001383 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1384 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1385 mInputReceiver->sendTimeline(inputEventId, timeline);
1386 }
1387
chaviwaf87b3e2019-10-01 16:59:28 -07001388 InputEvent* consume() {
1389 if (mInputReceiver == nullptr) {
1390 return nullptr;
1391 }
1392 return mInputReceiver->consume();
1393 }
1394
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001395 MotionEvent* consumeMotion() {
1396 InputEvent* event = consume();
1397 if (event == nullptr) {
1398 ADD_FAILURE() << "Consume failed : no event";
1399 return nullptr;
1400 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001401 if (event->getType() != InputEventType::MOTION) {
1402 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001403 return nullptr;
1404 }
1405 return static_cast<MotionEvent*>(event);
1406 }
1407
Arthur Hungb92218b2018-08-14 12:00:21 +08001408 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001409 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001410 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001411 return; // Can't receive events if the window does not have input channel
1412 }
1413 ASSERT_NE(nullptr, mInputReceiver)
1414 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001415 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001416 }
1417
chaviwaf87b3e2019-10-01 16:59:28 -07001418 sp<IBinder> getToken() { return mInfo.token; }
1419
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001420 const std::string& getName() { return mName; }
1421
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001422 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001423 mInfo.ownerPid = ownerPid;
1424 mInfo.ownerUid = ownerUid;
1425 }
1426
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001427 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001428
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001429 void destroyReceiver() { mInputReceiver = nullptr; }
1430
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001431 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1432
chaviwd1c23182019-12-20 18:44:56 -08001433private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001434 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001435 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001436 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001437 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001438 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001439};
1440
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001441std::atomic<int32_t> FakeWindowHandle::sId{1};
1442
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001443static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001444 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001445 int32_t displayId = ADISPLAY_ID_NONE,
1446 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001447 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001448 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001449 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001450 KeyEvent event;
1451 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1452
1453 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001454 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001455 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1456 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001457
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001458 if (!allowKeyRepeat) {
1459 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1460 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001461 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001462 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001463}
1464
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001465static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001466 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001467 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001468}
1469
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001470// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1471// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1472// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001473static InputEventInjectionResult injectKeyDownNoRepeat(
1474 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001475 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001476 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001477 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001478}
1479
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001480static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001481 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001482 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001483}
1484
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001485static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001486 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001487 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001488 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001489 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001490 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1491 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001492}
1493
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001494static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001495 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001496 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001497 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001498 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1499 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001500 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001501 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001502 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001503 MotionEventBuilder motionBuilder =
1504 MotionEventBuilder(action, source)
1505 .displayId(displayId)
1506 .eventTime(eventTime)
1507 .rawXCursorPosition(cursorPosition.x)
1508 .rawYCursorPosition(cursorPosition.y)
1509 .pointer(
1510 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1511 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1512 motionBuilder.downTime(eventTime);
1513 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001514
1515 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001516 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1517 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001518}
1519
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001520static InputEventInjectionResult injectMotionDown(
1521 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1522 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001523 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001524}
1525
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001526static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001527 int32_t source, int32_t displayId,
1528 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001529 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001530}
1531
Jackal Guof9696682018-10-05 12:23:23 +08001532static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1533 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1534 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001535 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001536 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1537 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001538
1539 return args;
1540}
1541
Josep del Riob3981622023-04-18 15:49:45 +00001542static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1543 int32_t displayId = ADISPLAY_ID_NONE) {
1544 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1545 // Define a valid key event.
1546 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001547 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001548 currentTime);
1549
1550 return args;
1551}
1552
1553static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1554 int32_t displayId = ADISPLAY_ID_NONE) {
1555 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1556 // Define a valid key event.
1557 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001558 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001559 AMETA_NONE, currentTime);
1560
1561 return args;
1562}
1563
Prabir Pradhan678438e2023-04-13 19:32:51 +00001564[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1565 int32_t displayId,
1566 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001567 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001568 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1569 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1570 }
1571
chaviwd1c23182019-12-20 18:44:56 -08001572 PointerProperties pointerProperties[pointerCount];
1573 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001574
chaviwd1c23182019-12-20 18:44:56 -08001575 for (size_t i = 0; i < pointerCount; i++) {
1576 pointerProperties[i].clear();
1577 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001578 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001579
chaviwd1c23182019-12-20 18:44:56 -08001580 pointerCoords[i].clear();
1581 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1582 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1583 }
Jackal Guof9696682018-10-05 12:23:23 +08001584
1585 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1586 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001587 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001588 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1589 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001590 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001591 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001592 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001593 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001594
1595 return args;
1596}
1597
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001598static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1599 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1600}
1601
chaviwd1c23182019-12-20 18:44:56 -08001602static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1603 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1604}
1605
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001606static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1607 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001608 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001609}
1610
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001611} // namespace
1612
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001613/**
1614 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1615 * broken channel.
1616 */
1617TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1619 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001620 sp<FakeWindowHandle>::make(application, mDispatcher,
1621 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001622
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001623 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001624
1625 // Window closes its channel, but the window remains.
1626 window->destroyReceiver();
1627 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1628}
1629
Arthur Hungb92218b2018-08-14 12:00:21 +08001630TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001632 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1633 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001634
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001635 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1637 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001639
1640 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001641 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001642}
1643
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001644TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001646 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1647 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001648
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001650 // Inject a MotionEvent to an unknown display.
1651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1652 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1654
1655 // Window should receive motion event.
1656 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1657}
1658
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001659/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001660 * Calling onWindowInfosChanged once should not cause any issues.
1661 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001662 * called twice.
1663 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001664TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001666 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1667 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001668 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001669
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001672 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1673 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001675
1676 // Window should receive motion event.
1677 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1678}
1679
1680/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001681 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001682 */
1683TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001685 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1686 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001689 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1690 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001692 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1693 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695
1696 // Window should receive motion event.
1697 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1698}
1699
Arthur Hungb92218b2018-08-14 12:00:21 +08001700// The foreground window should receive the first touch down event.
1701TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001703 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001704 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001705 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001706 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001707
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001708 mDispatcher->onWindowInfosChanged(
1709 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1711 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001713
1714 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001715 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001716 windowSecond->assertNoEvents();
1717}
1718
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001719/**
1720 * Two windows: A top window, and a wallpaper behind the window.
1721 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1722 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001723 * 1. foregroundWindow <-- dup touch to wallpaper
1724 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001725 */
1726TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1728 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001729 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001730 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001731 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001733 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001734
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001735 mDispatcher->onWindowInfosChanged(
1736 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1738 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1739 {100, 200}))
1740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1741
1742 // Both foreground window and its wallpaper should receive the touch down
1743 foregroundWindow->consumeMotionDown();
1744 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1745
1746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1747 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1748 ADISPLAY_ID_DEFAULT, {110, 200}))
1749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1750
1751 foregroundWindow->consumeMotionMove();
1752 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1753
1754 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001755 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001756 foregroundWindow->consumeMotionCancel();
1757 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1758 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1759}
1760
1761/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001762 * Two fingers down on the window, and lift off the first finger.
1763 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1764 * contains a single pointer.
1765 */
1766TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1768 sp<FakeWindowHandle> window =
1769 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1770
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001771 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001772 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001773 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1774 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1775 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001776 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001777 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1778 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1779 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1780 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001781 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001782 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1783 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1784 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1785 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001786 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1787 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1788 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1789
1790 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001792 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1793 window->consumeMotionEvent(
1794 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1795}
1796
1797/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001798 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1799 * with the following differences:
1800 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1801 * clean up the connection.
1802 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1803 * Ensure that there's no crash in the dispatcher.
1804 */
1805TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1807 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001808 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001809 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001810 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001811 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001812 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001814 mDispatcher->onWindowInfosChanged(
1815 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1817 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1818 {100, 200}))
1819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1820
1821 // Both foreground window and its wallpaper should receive the touch down
1822 foregroundWindow->consumeMotionDown();
1823 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1824
1825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1826 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1827 ADISPLAY_ID_DEFAULT, {110, 200}))
1828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1829
1830 foregroundWindow->consumeMotionMove();
1831 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1832
1833 // Wallpaper closes its channel, but the window remains.
1834 wallpaperWindow->destroyReceiver();
1835 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1836
1837 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1838 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001839 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001840 foregroundWindow->consumeMotionCancel();
1841}
1842
Arthur Hungc539dbb2022-12-08 07:45:36 +00001843class ShouldSplitTouchFixture : public InputDispatcherTest,
1844 public ::testing::WithParamInterface<bool> {};
1845INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1846 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001847/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001848 * A single window that receives touch (on top), and a wallpaper window underneath it.
1849 * The top window gets a multitouch gesture.
1850 * Ensure that wallpaper gets the same gesture.
1851 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001852TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001854 sp<FakeWindowHandle> foregroundWindow =
1855 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1856 foregroundWindow->setDupTouchToWallpaper(true);
1857 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001858
1859 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001860 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001861 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001863 mDispatcher->onWindowInfosChanged(
1864 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001865
1866 // Touch down on top window
1867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1868 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1869 {100, 100}))
1870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1871
1872 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001873 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001874 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1875
1876 // Second finger down on the top window
1877 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001878 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001880 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1881 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882 .build();
1883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1884 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1885 InputEventInjectionSync::WAIT_FOR_RESULT))
1886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1887
Harry Cutts33476232023-01-30 19:57:29 +00001888 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1889 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001891
1892 const MotionEvent secondFingerUpEvent =
1893 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1894 .displayId(ADISPLAY_ID_DEFAULT)
1895 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001896 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1897 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001898 .build();
1899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1900 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1901 InputEventInjectionSync::WAIT_FOR_RESULT))
1902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1903 foregroundWindow->consumeMotionPointerUp(0);
1904 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1905
1906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001907 injectMotionEvent(mDispatcher,
1908 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1909 AINPUT_SOURCE_TOUCHSCREEN)
1910 .displayId(ADISPLAY_ID_DEFAULT)
1911 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001912 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001913 .x(100)
1914 .y(100))
1915 .build(),
1916 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1918 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1919 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001920}
1921
1922/**
1923 * Two windows: a window on the left and window on the right.
1924 * A third window, wallpaper, is behind both windows, and spans both top windows.
1925 * The first touch down goes to the left window. A second pointer touches down on the right window.
1926 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1927 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1928 * ACTION_POINTER_DOWN(1).
1929 */
1930TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1932 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001933 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001935 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936
1937 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001938 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001939 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001940 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941
1942 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001943 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001944 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001945 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001947 mDispatcher->onWindowInfosChanged(
1948 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1949 {},
1950 0,
1951 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952
1953 // Touch down on left window
1954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1955 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1956 {100, 100}))
1957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1958
1959 // Both foreground window and its wallpaper should receive the touch down
1960 leftWindow->consumeMotionDown();
1961 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1962
1963 // Second finger down on the right window
1964 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001965 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001966 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001967 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1968 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001969 .build();
1970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1971 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1972 InputEventInjectionSync::WAIT_FOR_RESULT))
1973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1974
1975 leftWindow->consumeMotionMove();
1976 // Since the touch is split, right window gets ACTION_DOWN
1977 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001978 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979 expectedWallpaperFlags);
1980
1981 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001982 mDispatcher->onWindowInfosChanged(
1983 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984 leftWindow->consumeMotionCancel();
1985 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1986 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1987
1988 // The pointer that's still down on the right window moves, and goes to the right window only.
1989 // As far as the dispatcher's concerned though, both pointers are still present.
1990 const MotionEvent secondFingerMoveEvent =
1991 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1992 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001993 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1994 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995 .build();
1996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1997 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1998 InputEventInjectionSync::WAIT_FOR_RESULT));
1999 rightWindow->consumeMotionMove();
2000
2001 leftWindow->assertNoEvents();
2002 rightWindow->assertNoEvents();
2003 wallpaperWindow->assertNoEvents();
2004}
2005
Arthur Hungc539dbb2022-12-08 07:45:36 +00002006/**
2007 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2008 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2009 * The right window should receive ACTION_DOWN.
2010 */
2011TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002013 sp<FakeWindowHandle> leftWindow =
2014 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2015 leftWindow->setFrame(Rect(0, 0, 200, 200));
2016 leftWindow->setDupTouchToWallpaper(true);
2017 leftWindow->setSlippery(true);
2018
2019 sp<FakeWindowHandle> rightWindow =
2020 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2021 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002022
2023 sp<FakeWindowHandle> wallpaperWindow =
2024 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2025 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002026
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002027 mDispatcher->onWindowInfosChanged(
2028 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2029 {},
2030 0,
2031 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002032
Arthur Hungc539dbb2022-12-08 07:45:36 +00002033 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2035 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002036 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002038
2039 // Both foreground window and its wallpaper should receive the touch down
2040 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002041 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2042
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2046 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2048
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049 leftWindow->consumeMotionCancel();
2050 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2051 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002052}
2053
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002054/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002055 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2056 * interactive, it might stop sending this flag.
2057 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2058 * to have a consistent input stream.
2059 *
2060 * Test procedure:
2061 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2062 * DOWN (new gesture).
2063 *
2064 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2065 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2066 *
2067 * We technically just need a single window here, but we are using two windows (spy on top and a
2068 * regular window below) to emulate the actual situation where it happens on the device.
2069 */
2070TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2072 sp<FakeWindowHandle> spyWindow =
2073 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2074 spyWindow->setFrame(Rect(0, 0, 200, 200));
2075 spyWindow->setTrustedOverlay(true);
2076 spyWindow->setSpy(true);
2077
2078 sp<FakeWindowHandle> window =
2079 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2080 window->setFrame(Rect(0, 0, 200, 200));
2081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002082 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002083 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002084
2085 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002086 mDispatcher->notifyMotion(
2087 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2088 .deviceId(touchDeviceId)
2089 .policyFlags(DEFAULT_POLICY_FLAGS)
2090 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2091 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002092
Prabir Pradhan678438e2023-04-13 19:32:51 +00002093 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2094 .deviceId(touchDeviceId)
2095 .policyFlags(DEFAULT_POLICY_FLAGS)
2096 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2097 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2098 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002099 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2100 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2101 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2102 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2103
2104 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002105 mDispatcher->notifyMotion(
2106 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2107 .deviceId(touchDeviceId)
2108 .policyFlags(0)
2109 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2110 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2111 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002112 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2113 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2114
2115 // We don't need to reset the device to reproduce the issue, but the reset event typically
2116 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002117 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002118
2119 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002120 mDispatcher->notifyMotion(
2121 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2122 .deviceId(touchDeviceId)
2123 .policyFlags(DEFAULT_POLICY_FLAGS)
2124 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2125 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2127 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2128
2129 // No more events
2130 spyWindow->assertNoEvents();
2131 window->assertNoEvents();
2132}
2133
2134/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002135 * Two windows: a window on the left and a window on the right.
2136 * Mouse is hovered from the right window into the left window.
2137 * Next, we tap on the left window, where the cursor was last seen.
2138 * The second tap is done onto the right window.
2139 * The mouse and tap are from two different devices.
2140 * We technically don't need to set the downtime / eventtime for these events, but setting these
2141 * explicitly helps during debugging.
2142 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2143 * In the buggy implementation, a tap on the right window would cause a crash.
2144 */
2145TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2147 sp<FakeWindowHandle> leftWindow =
2148 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2149 leftWindow->setFrame(Rect(0, 0, 200, 200));
2150
2151 sp<FakeWindowHandle> rightWindow =
2152 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2153 rightWindow->setFrame(Rect(200, 0, 400, 200));
2154
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002155 mDispatcher->onWindowInfosChanged(
2156 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002157 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2158 // stale.
2159 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2160 const int32_t mouseDeviceId = 6;
2161 const int32_t touchDeviceId = 4;
2162 // Move the cursor from right
2163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2164 injectMotionEvent(mDispatcher,
2165 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2166 AINPUT_SOURCE_MOUSE)
2167 .deviceId(mouseDeviceId)
2168 .downTime(baseTime + 10)
2169 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002170 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002171 .x(300)
2172 .y(100))
2173 .build()));
2174 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2175
2176 // .. to the left window
2177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2178 injectMotionEvent(mDispatcher,
2179 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2180 AINPUT_SOURCE_MOUSE)
2181 .deviceId(mouseDeviceId)
2182 .downTime(baseTime + 10)
2183 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002184 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 .x(110)
2186 .y(100))
2187 .build()));
2188 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2189 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2190 // Now tap the left window
2191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2192 injectMotionEvent(mDispatcher,
2193 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2194 AINPUT_SOURCE_TOUCHSCREEN)
2195 .deviceId(touchDeviceId)
2196 .downTime(baseTime + 40)
2197 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002198 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002199 .x(100)
2200 .y(100))
2201 .build()));
2202 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2203 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2204
2205 // release tap
2206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2207 injectMotionEvent(mDispatcher,
2208 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2209 AINPUT_SOURCE_TOUCHSCREEN)
2210 .deviceId(touchDeviceId)
2211 .downTime(baseTime + 40)
2212 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002213 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002214 .x(100)
2215 .y(100))
2216 .build()));
2217 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2218
2219 // Tap the window on the right
2220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2221 injectMotionEvent(mDispatcher,
2222 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2223 AINPUT_SOURCE_TOUCHSCREEN)
2224 .deviceId(touchDeviceId)
2225 .downTime(baseTime + 60)
2226 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002227 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002228 .x(300)
2229 .y(100))
2230 .build()));
2231 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2232
2233 // release tap
2234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2235 injectMotionEvent(mDispatcher,
2236 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2237 AINPUT_SOURCE_TOUCHSCREEN)
2238 .deviceId(touchDeviceId)
2239 .downTime(baseTime + 60)
2240 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002241 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002242 .x(300)
2243 .y(100))
2244 .build()));
2245 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2246
2247 // No more events
2248 leftWindow->assertNoEvents();
2249 rightWindow->assertNoEvents();
2250}
2251
2252/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002253 * Start hovering in a window. While this hover is still active, make another window appear on top.
2254 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2255 * While the top window is present, the hovering is stopped.
2256 * Later, hovering gets resumed again.
2257 * Ensure that new hover gesture is handled correctly.
2258 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2259 * to the window that's currently being hovered over.
2260 */
2261TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2262 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2263 sp<FakeWindowHandle> window =
2264 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2265 window->setFrame(Rect(0, 0, 200, 200));
2266
2267 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002268 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002269
2270 // Start hovering in the window
2271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2272 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2273 .build());
2274 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2275
2276 // Now, an obscuring window appears!
2277 sp<FakeWindowHandle> obscuringWindow =
2278 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2279 ADISPLAY_ID_DEFAULT,
2280 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2281 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2282 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2283 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2284 obscuringWindow->setNoInputChannel(true);
2285 obscuringWindow->setFocusable(false);
2286 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002287 mDispatcher->onWindowInfosChanged(
2288 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002289
2290 // While this new obscuring window is present, the hovering is stopped
2291 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2292 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2293 .build());
2294 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2295
2296 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002297 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002298
2299 // And a new hover gesture starts.
2300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2301 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2302 .build());
2303 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2304}
2305
2306/**
2307 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2308 * the obscuring window.
2309 */
2310TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2311 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2312 sp<FakeWindowHandle> window =
2313 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2314 window->setFrame(Rect(0, 0, 200, 200));
2315
2316 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002317 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002318
2319 // Start hovering in the window
2320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2321 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2322 .build());
2323 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2324
2325 // Now, an obscuring window appears!
2326 sp<FakeWindowHandle> obscuringWindow =
2327 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2328 ADISPLAY_ID_DEFAULT,
2329 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2330 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2331 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2332 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2333 obscuringWindow->setNoInputChannel(true);
2334 obscuringWindow->setFocusable(false);
2335 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002336 mDispatcher->onWindowInfosChanged(
2337 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002338
2339 // While this new obscuring window is present, the hovering continues. The event can't go to the
2340 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2342 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2343 .build());
2344 obscuringWindow->assertNoEvents();
2345 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2346
2347 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002349
2350 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2351 // so it should generate a HOVER_ENTER
2352 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2353 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2354 .build());
2355 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2356
2357 // Now the MOVE should be getting dispatched normally
2358 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2359 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2360 .build());
2361 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2362}
2363
2364/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002365 * Two windows: a window on the left and a window on the right.
2366 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2367 * down. Then, on the left window, also place second touch pointer down.
2368 * This test tries to reproduce a crash.
2369 * In the buggy implementation, second pointer down on the left window would cause a crash.
2370 */
2371TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2373 sp<FakeWindowHandle> leftWindow =
2374 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2375 leftWindow->setFrame(Rect(0, 0, 200, 200));
2376
2377 sp<FakeWindowHandle> rightWindow =
2378 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2379 rightWindow->setFrame(Rect(200, 0, 400, 200));
2380
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002381 mDispatcher->onWindowInfosChanged(
2382 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002383
2384 const int32_t touchDeviceId = 4;
2385 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002386
2387 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2389 .deviceId(mouseDeviceId)
2390 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2391 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002392 leftWindow->consumeMotionEvent(
2393 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2394
2395 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002396 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2397 .deviceId(mouseDeviceId)
2398 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2399 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2400 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002401
2402 leftWindow->consumeMotionEvent(
2403 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2404 leftWindow->consumeMotionEvent(
2405 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2406
Prabir Pradhan678438e2023-04-13 19:32:51 +00002407 mDispatcher->notifyMotion(
2408 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2409 .deviceId(mouseDeviceId)
2410 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2411 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2412 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2413 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002414 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2415
2416 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2420 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002421 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2422
2423 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2424
2425 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002426 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2427 .deviceId(touchDeviceId)
2428 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2429 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2430 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002431 leftWindow->consumeMotionEvent(
2432 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2433 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2434 // current implementation.
2435 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2436 rightWindow->consumeMotionEvent(
2437 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2438
2439 leftWindow->assertNoEvents();
2440 rightWindow->assertNoEvents();
2441}
2442
2443/**
2444 * On a single window, use two different devices: mouse and touch.
2445 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2446 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2447 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2448 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2449 * represent a new gesture.
2450 */
2451TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2452 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2453 sp<FakeWindowHandle> window =
2454 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2455 window->setFrame(Rect(0, 0, 400, 400));
2456
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002457 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002458
2459 const int32_t touchDeviceId = 4;
2460 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002461
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002462 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2464 .deviceId(touchDeviceId)
2465 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2466 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002467 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002468 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2469 .deviceId(touchDeviceId)
2470 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2471 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2472 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002473 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002474 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2475 .deviceId(touchDeviceId)
2476 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2477 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2478 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002479 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2480 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2481 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2482
2483 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2485 .deviceId(mouseDeviceId)
2486 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2487 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2488 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002489
2490 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002491 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002492 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2493
Prabir Pradhan678438e2023-04-13 19:32:51 +00002494 mDispatcher->notifyMotion(
2495 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2496 .deviceId(mouseDeviceId)
2497 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2498 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2499 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2500 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002501 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2502
2503 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002504 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2505 .deviceId(touchDeviceId)
2506 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2507 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2508 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002509 // The pointer_down event should be ignored
2510 window->assertNoEvents();
2511}
2512
2513/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002514 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2515 * the injected event.
2516 */
2517TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2519 sp<FakeWindowHandle> window =
2520 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2521 window->setFrame(Rect(0, 0, 400, 400));
2522
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002523 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002524
2525 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002526 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2527 // completion.
2528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2529 injectMotionEvent(mDispatcher,
2530 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2531 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002532 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002533 .x(50)
2534 .y(50))
2535 .build()));
2536 window->consumeMotionEvent(
2537 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2538
2539 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2540 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2542 .deviceId(touchDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2544 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002545
2546 window->consumeMotionEvent(
2547 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2548 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2549}
2550
2551/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002552 * This test is similar to the test above, but the sequence of injected events is different.
2553 *
2554 * Two windows: a window on the left and a window on the right.
2555 * Mouse is hovered over the left window.
2556 * Next, we tap on the left window, where the cursor was last seen.
2557 *
2558 * After that, we inject one finger down onto the right window, and then a second finger down onto
2559 * the left window.
2560 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2561 * window (first), and then another on the left window (second).
2562 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2563 * In the buggy implementation, second finger down on the left window would cause a crash.
2564 */
2565TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2567 sp<FakeWindowHandle> leftWindow =
2568 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2569 leftWindow->setFrame(Rect(0, 0, 200, 200));
2570
2571 sp<FakeWindowHandle> rightWindow =
2572 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2573 rightWindow->setFrame(Rect(200, 0, 400, 200));
2574
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002575 mDispatcher->onWindowInfosChanged(
2576 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002577
2578 const int32_t mouseDeviceId = 6;
2579 const int32_t touchDeviceId = 4;
2580 // Hover over the left window. Keep the cursor there.
2581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2582 injectMotionEvent(mDispatcher,
2583 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2584 AINPUT_SOURCE_MOUSE)
2585 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002586 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002587 .x(50)
2588 .y(50))
2589 .build()));
2590 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2591
2592 // Tap on left window
2593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2594 injectMotionEvent(mDispatcher,
2595 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2596 AINPUT_SOURCE_TOUCHSCREEN)
2597 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002598 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002599 .x(100)
2600 .y(100))
2601 .build()));
2602
2603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2604 injectMotionEvent(mDispatcher,
2605 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2606 AINPUT_SOURCE_TOUCHSCREEN)
2607 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002608 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002609 .x(100)
2610 .y(100))
2611 .build()));
2612 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2613 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2614 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2615
2616 // First finger down on right window
2617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2618 injectMotionEvent(mDispatcher,
2619 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2620 AINPUT_SOURCE_TOUCHSCREEN)
2621 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002622 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002623 .x(300)
2624 .y(100))
2625 .build()));
2626 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2627
2628 // Second finger down on the left window
2629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2630 injectMotionEvent(mDispatcher,
2631 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2632 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002633 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002634 .x(300)
2635 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002636 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002637 .x(100)
2638 .y(100))
2639 .build()));
2640 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2641 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2642
2643 // No more events
2644 leftWindow->assertNoEvents();
2645 rightWindow->assertNoEvents();
2646}
2647
2648/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002649 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2650 * While the touch is down, new hover events from the stylus device should be ignored. After the
2651 * touch is gone, stylus hovering should start working again.
2652 */
2653TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2655 sp<FakeWindowHandle> window =
2656 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2657 window->setFrame(Rect(0, 0, 200, 200));
2658
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002659 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002660
2661 const int32_t stylusDeviceId = 5;
2662 const int32_t touchDeviceId = 4;
2663 // Start hovering with stylus
2664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2665 injectMotionEvent(mDispatcher,
2666 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2667 AINPUT_SOURCE_STYLUS)
2668 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002669 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002670 .x(50)
2671 .y(50))
2672 .build()));
2673 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2674
2675 // Finger down on the window
2676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2677 injectMotionEvent(mDispatcher,
2678 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2679 AINPUT_SOURCE_TOUCHSCREEN)
2680 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002681 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002682 .x(100)
2683 .y(100))
2684 .build()));
2685 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2686 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2687
2688 // Try to continue hovering with stylus. Since we are already down, injection should fail
2689 ASSERT_EQ(InputEventInjectionResult::FAILED,
2690 injectMotionEvent(mDispatcher,
2691 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2692 AINPUT_SOURCE_STYLUS)
2693 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002694 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002695 .build()));
2696 // No event should be sent. This event should be ignored because a pointer from another device
2697 // is already down.
2698
2699 // Lift up the finger
2700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2701 injectMotionEvent(mDispatcher,
2702 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2703 AINPUT_SOURCE_TOUCHSCREEN)
2704 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002705 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002706 .x(100)
2707 .y(100))
2708 .build()));
2709 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2710
2711 // Now that the touch is gone, stylus hovering should start working again
2712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2713 injectMotionEvent(mDispatcher,
2714 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2715 AINPUT_SOURCE_STYLUS)
2716 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002717 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002718 .build()));
2719 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2720 // No more events
2721 window->assertNoEvents();
2722}
2723
2724/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002725 * A spy window above a window with no input channel.
2726 * Start hovering with a stylus device, and then tap with it.
2727 * Ensure spy window receives the entire sequence.
2728 */
2729TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2731 sp<FakeWindowHandle> spyWindow =
2732 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2733 spyWindow->setFrame(Rect(0, 0, 200, 200));
2734 spyWindow->setTrustedOverlay(true);
2735 spyWindow->setSpy(true);
2736 sp<FakeWindowHandle> window =
2737 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2738 window->setNoInputChannel(true);
2739 window->setFrame(Rect(0, 0, 200, 200));
2740
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002741 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002742
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002743 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2745 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2746 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002747 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2748 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2750 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2751 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002752 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2753
2754 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2756 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2757 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002758 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2759
2760 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002761 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2762 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2763 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002764 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2765
2766 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2768 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2769 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002770 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2771 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2773 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2774 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002775 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2776
2777 // No more events
2778 spyWindow->assertNoEvents();
2779 window->assertNoEvents();
2780}
2781
2782/**
2783 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2784 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2785 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2786 * While the mouse is down, new move events from the touch device should be ignored.
2787 */
2788TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2790 sp<FakeWindowHandle> spyWindow =
2791 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2792 spyWindow->setFrame(Rect(0, 0, 200, 200));
2793 spyWindow->setTrustedOverlay(true);
2794 spyWindow->setSpy(true);
2795 sp<FakeWindowHandle> window =
2796 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2797 window->setFrame(Rect(0, 0, 200, 200));
2798
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002799 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002800
2801 const int32_t mouseDeviceId = 7;
2802 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002803
2804 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002805 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2806 .deviceId(mouseDeviceId)
2807 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2808 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002809 spyWindow->consumeMotionEvent(
2810 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2811 window->consumeMotionEvent(
2812 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2813
2814 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002815 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2816 .deviceId(touchDeviceId)
2817 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2818 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002819 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2820 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2821 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2822 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2823
Prabir Pradhan678438e2023-04-13 19:32:51 +00002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2825 .deviceId(touchDeviceId)
2826 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2827 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002828 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2829 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2830
2831 // Pilfer the stream
2832 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2833 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2834
Prabir Pradhan678438e2023-04-13 19:32:51 +00002835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2836 .deviceId(touchDeviceId)
2837 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2838 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002839 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2840
2841 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2843 .deviceId(mouseDeviceId)
2844 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2845 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2846 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002847
2848 spyWindow->consumeMotionEvent(
2849 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2850 spyWindow->consumeMotionEvent(
2851 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2852 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2853
Prabir Pradhan678438e2023-04-13 19:32:51 +00002854 mDispatcher->notifyMotion(
2855 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2856 .deviceId(mouseDeviceId)
2857 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2858 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2859 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2860 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002861 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2862 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2863
2864 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2866 .deviceId(mouseDeviceId)
2867 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2868 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2869 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002870 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2871 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2872
2873 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2875 .deviceId(touchDeviceId)
2876 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2877 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002878
2879 // No more events
2880 spyWindow->assertNoEvents();
2881 window->assertNoEvents();
2882}
2883
2884/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002885 * On the display, have a single window, and also an area where there's no window.
2886 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2887 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2888 */
2889TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2891 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002892 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002893
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002894 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002895
2896 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002897 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002898
2899 mDispatcher->waitForIdle();
2900 window->assertNoEvents();
2901
2902 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002903 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002904 mDispatcher->waitForIdle();
2905 window->consumeMotionDown();
2906}
2907
2908/**
2909 * Same test as above, but instead of touching the empty space, the first touch goes to
2910 * non-touchable window.
2911 */
2912TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2913 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2914 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002915 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002916 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2917 window1->setTouchable(false);
2918 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002919 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002920 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2921
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002922 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002923
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002924 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002925 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002926
2927 mDispatcher->waitForIdle();
2928 window1->assertNoEvents();
2929 window2->assertNoEvents();
2930
2931 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002932 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002933 mDispatcher->waitForIdle();
2934 window2->consumeMotionDown();
2935}
2936
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002937/**
2938 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2939 * to the event time of the first ACTION_DOWN sent to the particular window.
2940 */
2941TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2943 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002944 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002945 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2946 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002947 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002948 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2949
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002950 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002951
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002952 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002953 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002954
2955 mDispatcher->waitForIdle();
2956 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002957 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002958 window2->assertNoEvents();
2959 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2960 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2961 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2962
2963 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002964 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 mDispatcher->waitForIdle();
2966 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002967 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002968 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2969 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2970 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2971 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2972
2973 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002974 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002975 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002976 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977
2978 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002979 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002980 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002981 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002982
2983 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2984 window1->consumeMotionMove();
2985 window1->assertNoEvents();
2986
2987 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002988 mDispatcher->notifyMotion(
2989 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002990 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002991 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002992
Prabir Pradhan678438e2023-04-13 19:32:51 +00002993 mDispatcher->notifyMotion(
2994 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002995 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002996 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002997}
2998
Garfield Tandf26e862020-07-01 20:18:19 -07002999TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003000 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003001 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003002 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003003 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003004 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003005 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003006 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003007
3008 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3009
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003010 mDispatcher->onWindowInfosChanged(
3011 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003012
3013 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003015 injectMotionEvent(mDispatcher,
3016 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3017 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003018 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003019 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003020 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003021
3022 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003024 injectMotionEvent(mDispatcher,
3025 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3026 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003027 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003028 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003029 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3030 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003031
3032 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003034 injectMotionEvent(mDispatcher,
3035 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3036 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003037 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003038 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003039 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3040 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003041
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003043 injectMotionEvent(mDispatcher,
3044 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3045 AINPUT_SOURCE_MOUSE)
3046 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3047 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003048 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003049 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003050 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003051
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003053 injectMotionEvent(mDispatcher,
3054 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3055 AINPUT_SOURCE_MOUSE)
3056 .buttonState(0)
3057 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003058 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003059 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003060 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003061
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003063 injectMotionEvent(mDispatcher,
3064 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3065 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003066 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003067 .build()));
3068 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3069
3070 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003072 injectMotionEvent(mDispatcher,
3073 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3074 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003075 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003076 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003077 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003078
3079 // No more events
3080 windowLeft->assertNoEvents();
3081 windowRight->assertNoEvents();
3082}
3083
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003084/**
3085 * Put two fingers down (and don't release them) and click the mouse button.
3086 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3087 * currently active gesture should be canceled, and the new one should proceed.
3088 */
3089TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3091 sp<FakeWindowHandle> window =
3092 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3093 window->setFrame(Rect(0, 0, 600, 800));
3094
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003095 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003096
3097 const int32_t touchDeviceId = 4;
3098 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003099
3100 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3102 .deviceId(touchDeviceId)
3103 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3104 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003105
Prabir Pradhan678438e2023-04-13 19:32:51 +00003106 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3107 .deviceId(touchDeviceId)
3108 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3109 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3110 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003111 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3112 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3113
3114 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003115 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3116 .deviceId(mouseDeviceId)
3117 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3118 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3119 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3121 WithPointerCount(2u)));
3122 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3123
Prabir Pradhan678438e2023-04-13 19:32:51 +00003124 mDispatcher->notifyMotion(
3125 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3126 .deviceId(mouseDeviceId)
3127 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3128 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3129 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3130 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003131 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3132
3133 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3134 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003135 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3136 .deviceId(touchDeviceId)
3137 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3138 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3139 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 window->assertNoEvents();
3141}
3142
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003143TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3145
3146 sp<FakeWindowHandle> spyWindow =
3147 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3148 spyWindow->setFrame(Rect(0, 0, 600, 800));
3149 spyWindow->setTrustedOverlay(true);
3150 spyWindow->setSpy(true);
3151 sp<FakeWindowHandle> window =
3152 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3153 window->setFrame(Rect(0, 0, 600, 800));
3154
3155 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003156 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003157
3158 // Send mouse cursor to the window
3159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3160 injectMotionEvent(mDispatcher,
3161 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3162 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003163 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003164 .x(100)
3165 .y(100))
3166 .build()));
3167
3168 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3169 WithSource(AINPUT_SOURCE_MOUSE)));
3170 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3171 WithSource(AINPUT_SOURCE_MOUSE)));
3172
3173 window->assertNoEvents();
3174 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003175}
3176
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003177TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3179
3180 sp<FakeWindowHandle> spyWindow =
3181 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3182 spyWindow->setFrame(Rect(0, 0, 600, 800));
3183 spyWindow->setTrustedOverlay(true);
3184 spyWindow->setSpy(true);
3185 sp<FakeWindowHandle> window =
3186 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3187 window->setFrame(Rect(0, 0, 600, 800));
3188
3189 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003190 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003191
3192 // Send mouse cursor to the window
3193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3194 injectMotionEvent(mDispatcher,
3195 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3196 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003197 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003198 .x(100)
3199 .y(100))
3200 .build()));
3201
3202 // Move mouse cursor
3203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3204 injectMotionEvent(mDispatcher,
3205 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3206 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003207 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003208 .x(110)
3209 .y(110))
3210 .build()));
3211
3212 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3213 WithSource(AINPUT_SOURCE_MOUSE)));
3214 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3215 WithSource(AINPUT_SOURCE_MOUSE)));
3216 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3217 WithSource(AINPUT_SOURCE_MOUSE)));
3218 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3219 WithSource(AINPUT_SOURCE_MOUSE)));
3220 // Touch down on the window
3221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3222 injectMotionEvent(mDispatcher,
3223 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3224 AINPUT_SOURCE_TOUCHSCREEN)
3225 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003226 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003227 .x(200)
3228 .y(200))
3229 .build()));
3230 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3231 WithSource(AINPUT_SOURCE_MOUSE)));
3232 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3233 WithSource(AINPUT_SOURCE_MOUSE)));
3234 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3235 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3236 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3237 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3238
3239 // pilfer the motion, retaining the gesture on the spy window.
3240 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3241 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3242 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3243
3244 // Touch UP on the window
3245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3246 injectMotionEvent(mDispatcher,
3247 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3248 AINPUT_SOURCE_TOUCHSCREEN)
3249 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003250 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003251 .x(200)
3252 .y(200))
3253 .build()));
3254 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3255 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3256
3257 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3258 // to send a new gesture. It should again go to both windows (spy and the window below), just
3259 // like the first gesture did, before pilfering. The window configuration has not changed.
3260
3261 // One more tap - DOWN
3262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3263 injectMotionEvent(mDispatcher,
3264 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3265 AINPUT_SOURCE_TOUCHSCREEN)
3266 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003267 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003268 .x(250)
3269 .y(250))
3270 .build()));
3271 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3272 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3273 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3274 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3275
3276 // Touch UP on the window
3277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3278 injectMotionEvent(mDispatcher,
3279 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
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_UP),
3287 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3288 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3289 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3290
3291 window->assertNoEvents();
3292 spyWindow->assertNoEvents();
3293}
3294
Garfield Tandf26e862020-07-01 20:18:19 -07003295// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3296// directly in this test.
3297TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003299 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003300 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003301 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003302
3303 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003306
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003308 injectMotionEvent(mDispatcher,
3309 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3310 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003311 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003312 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003313 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003314 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003316 injectMotionEvent(mDispatcher,
3317 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3318 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003320 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003321 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3322 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003323
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003325 injectMotionEvent(mDispatcher,
3326 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3327 AINPUT_SOURCE_MOUSE)
3328 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3329 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003330 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003331 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003332 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003333
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003335 injectMotionEvent(mDispatcher,
3336 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3337 AINPUT_SOURCE_MOUSE)
3338 .buttonState(0)
3339 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003340 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003341 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003342 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003343
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003345 injectMotionEvent(mDispatcher,
3346 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3347 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003348 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003349 .build()));
3350 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3351
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003352 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3353 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3354 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003355 injectMotionEvent(mDispatcher,
3356 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3357 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003358 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003359 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003360 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003361}
3362
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003363/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003364 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3365 * is generated.
3366 */
3367TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3369 sp<FakeWindowHandle> window =
3370 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3371 window->setFrame(Rect(0, 0, 1200, 800));
3372
3373 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3374
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003375 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003376
3377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3378 injectMotionEvent(mDispatcher,
3379 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3380 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003381 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003382 .x(300)
3383 .y(400))
3384 .build()));
3385 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3386
3387 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003388 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003389 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3390}
3391
3392/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003393 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3394 */
3395TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3397 sp<FakeWindowHandle> window =
3398 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3399 window->setFrame(Rect(0, 0, 100, 100));
3400
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003401 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003402
3403 const int32_t mouseDeviceId = 7;
3404 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003405
3406 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3408 .deviceId(mouseDeviceId)
3409 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3410 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003411 window->consumeMotionEvent(
3412 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3413
3414 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3416 .deviceId(touchDeviceId)
3417 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3418 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003419
3420 window->consumeMotionEvent(
3421 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3422 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3423}
3424
3425/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003426 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003427 * The tap causes a HOVER_EXIT event to be generated because the current event
3428 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003429 */
3430TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3432 sp<FakeWindowHandle> window =
3433 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3434 window->setFrame(Rect(0, 0, 100, 100));
3435
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003436 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003437
3438 // Inject a hover_move from mouse.
3439 NotifyMotionArgs motionArgs =
3440 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3441 ADISPLAY_ID_DEFAULT, {{50, 50}});
3442 motionArgs.xCursorPosition = 50;
3443 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003444 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003445 ASSERT_NO_FATAL_FAILURE(
3446 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3447 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003448
3449 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003450 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3451 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3452 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003453 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003454 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3455 WithSource(AINPUT_SOURCE_MOUSE))));
3456
3457 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003458 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3459 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3460
Prabir Pradhan678438e2023-04-13 19:32:51 +00003461 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3462 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003463 ASSERT_NO_FATAL_FAILURE(
3464 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3465 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3466}
3467
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003468TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3470 sp<FakeWindowHandle> windowDefaultDisplay =
3471 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3472 ADISPLAY_ID_DEFAULT);
3473 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3474 sp<FakeWindowHandle> windowSecondDisplay =
3475 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3476 SECOND_DISPLAY_ID);
3477 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3478
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003479 mDispatcher->onWindowInfosChanged(
3480 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003481
3482 // Set cursor position in window in default display and check that hover enter and move
3483 // events are generated.
3484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3485 injectMotionEvent(mDispatcher,
3486 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3487 AINPUT_SOURCE_MOUSE)
3488 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003489 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003490 .x(300)
3491 .y(600))
3492 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003493 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003494
3495 // Remove all windows in secondary display and check that no event happens on window in
3496 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003497 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3498
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003499 windowDefaultDisplay->assertNoEvents();
3500
3501 // Move cursor position in window in default display and check that only hover move
3502 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003503 mDispatcher->onWindowInfosChanged(
3504 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3506 injectMotionEvent(mDispatcher,
3507 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3508 AINPUT_SOURCE_MOUSE)
3509 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003510 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003511 .x(400)
3512 .y(700))
3513 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003514 windowDefaultDisplay->consumeMotionEvent(
3515 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3516 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003517 windowDefaultDisplay->assertNoEvents();
3518}
3519
Garfield Tan00f511d2019-06-12 16:55:40 -07003520TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003521 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003522
3523 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003524 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003525 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003526 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003527 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003528 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003529
3530 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3531
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003532 mDispatcher->onWindowInfosChanged(
3533 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003534
3535 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3536 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003537 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003538 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003539 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003540 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003541 windowRight->assertNoEvents();
3542}
3543
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003544TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003546 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3547 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003548 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003549
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003550 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003551 setFocusedWindow(window);
3552
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003553 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003554
Prabir Pradhan678438e2023-04-13 19:32:51 +00003555 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003556
3557 // Window should receive key down event.
3558 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3559
3560 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3561 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003562 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003563 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003564 AKEY_EVENT_FLAG_CANCELED);
3565}
3566
3567TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003568 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003569 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3570 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003571
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003573
Prabir Pradhan678438e2023-04-13 19:32:51 +00003574 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3575 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003576
3577 // Window should receive motion down event.
3578 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3579
3580 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3581 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003582 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003583 window->consumeMotionEvent(
3584 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003585}
3586
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003587TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3589 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3590 "Fake Window", ADISPLAY_ID_DEFAULT);
3591
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003592 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003593
3594 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3595 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3596 .build());
3597
3598 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3599
3600 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3601 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3602 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3603
3604 // After the device has been reset, a new hovering stream can be sent to the window
3605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3606 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3607 .build());
3608 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3609}
3610
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003611TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3612 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003613 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3614 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003615 window->setFocusable(true);
3616
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003617 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003618 setFocusedWindow(window);
3619
3620 window->consumeFocusEvent(true);
3621
Prabir Pradhan678438e2023-04-13 19:32:51 +00003622 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003623 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3624 const nsecs_t injectTime = keyArgs.eventTime;
3625 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003626 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003627 // The dispatching time should be always greater than or equal to intercept key timeout.
3628 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3629 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3630 std::chrono::nanoseconds(interceptKeyTimeout).count());
3631}
3632
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003633/**
3634 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3635 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003636TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3637 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003638 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3639 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003640 window->setFocusable(true);
3641
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003642 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003643 setFocusedWindow(window);
3644
3645 window->consumeFocusEvent(true);
3646
Prabir Pradhan678438e2023-04-13 19:32:51 +00003647 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003648 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003649
3650 // Set a value that's significantly larger than the default consumption timeout. If the
3651 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3652 mFakePolicy->setInterceptKeyTimeout(600ms);
3653 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3654 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003655 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3656}
3657
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003658/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003659 * Two windows. First is a regular window. Second does not overlap with the first, and has
3660 * WATCH_OUTSIDE_TOUCH.
3661 * Both windows are owned by the same UID.
3662 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3663 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3664 */
3665TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3667 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3668 "First Window", ADISPLAY_ID_DEFAULT);
3669 window->setFrame(Rect{0, 0, 100, 100});
3670
3671 sp<FakeWindowHandle> outsideWindow =
3672 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3673 ADISPLAY_ID_DEFAULT);
3674 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3675 outsideWindow->setWatchOutsideTouch(true);
3676 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003677 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003678
3679 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003680 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3681 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3682 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003683 window->consumeMotionDown();
3684 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3685 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3686 outsideWindow->consumeMotionEvent(
3687 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3688}
3689
3690/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003691 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3692 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3693 * ACTION_OUTSIDE event is sent per gesture.
3694 */
3695TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3696 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003698 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3699 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003700 window->setWatchOutsideTouch(true);
3701 window->setFrame(Rect{0, 0, 100, 100});
3702 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003703 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3704 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003705 secondWindow->setFrame(Rect{100, 100, 200, 200});
3706 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003707 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3708 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003709 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003710 mDispatcher->onWindowInfosChanged(
3711 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003712
3713 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003714 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3715 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3716 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003717 window->assertNoEvents();
3718 secondWindow->assertNoEvents();
3719
3720 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3721 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003722 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3723 ADISPLAY_ID_DEFAULT,
3724 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003725 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3726 window->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003728 secondWindow->consumeMotionDown();
3729 thirdWindow->assertNoEvents();
3730
3731 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3732 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003733 mDispatcher->notifyMotion(
3734 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3735 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003736 window->assertNoEvents();
3737 secondWindow->consumeMotionMove();
3738 thirdWindow->consumeMotionDown();
3739}
3740
Prabir Pradhan814fe082022-07-22 20:22:18 +00003741TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003743 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3744 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003745 window->setFocusable(true);
3746
Patrick Williamsd828f302023-04-28 17:52:08 -05003747 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003748 setFocusedWindow(window);
3749
3750 window->consumeFocusEvent(true);
3751
Prabir Pradhan678438e2023-04-13 19:32:51 +00003752 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3753 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3754 mDispatcher->notifyKey(keyDown);
3755 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003756
3757 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3758 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3759
3760 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003761 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003762
3763 window->consumeFocusEvent(false);
3764
Prabir Pradhan678438e2023-04-13 19:32:51 +00003765 mDispatcher->notifyKey(keyDown);
3766 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003767 window->assertNoEvents();
3768}
3769
Arthur Hung96483742022-11-15 03:30:48 +00003770TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3772 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3773 "Fake Window", ADISPLAY_ID_DEFAULT);
3774 // Ensure window is non-split and have some transform.
3775 window->setPreventSplitting(true);
3776 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003777 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003778
3779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3780 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3781 {50, 50}))
3782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3783 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3784
3785 const MotionEvent secondFingerDownEvent =
3786 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3787 .displayId(ADISPLAY_ID_DEFAULT)
3788 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003789 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3790 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003791 .build();
3792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3793 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3794 InputEventInjectionSync::WAIT_FOR_RESULT))
3795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3796
3797 const MotionEvent* event = window->consumeMotion();
3798 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3799 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3800 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3801 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3802 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3803}
3804
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003805/**
3806 * Two windows: a splittable and a non-splittable.
3807 * The non-splittable window shouldn't receive any "incomplete" gestures.
3808 * Send the first pointer to the splittable window, and then touch the non-splittable window.
3809 * The second pointer should be dropped because the initial window is splittable, so it won't get
3810 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
3811 * "incomplete" gestures.
3812 */
3813TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
3814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3815 sp<FakeWindowHandle> leftWindow =
3816 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
3817 ADISPLAY_ID_DEFAULT);
3818 leftWindow->setPreventSplitting(false);
3819 leftWindow->setFrame(Rect(0, 0, 100, 100));
3820 sp<FakeWindowHandle> rightWindow =
3821 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
3822 ADISPLAY_ID_DEFAULT);
3823 rightWindow->setPreventSplitting(true);
3824 rightWindow->setFrame(Rect(100, 100, 200, 200));
3825 mDispatcher->onWindowInfosChanged(
3826 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3827
3828 // Touch down on left, splittable window
3829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3830 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3831 .build());
3832 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3833
3834 mDispatcher->notifyMotion(
3835 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3836 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3837 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
3838 .build());
3839 leftWindow->assertNoEvents();
3840 rightWindow->assertNoEvents();
3841}
3842
Harry Cuttsb166c002023-05-09 13:06:05 +00003843TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3845 sp<FakeWindowHandle> window =
3846 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3847 window->setFrame(Rect(0, 0, 400, 400));
3848 sp<FakeWindowHandle> trustedOverlay =
3849 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3850 ADISPLAY_ID_DEFAULT);
3851 trustedOverlay->setSpy(true);
3852 trustedOverlay->setTrustedOverlay(true);
3853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003854 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003855
3856 // Start a three-finger touchpad swipe
3857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3858 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3859 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3860 .build());
3861 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3862 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3863 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3864 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3865 .build());
3866 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3867 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3868 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3869 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3870 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3871 .build());
3872
3873 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3874 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3875 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3876
3877 // Move the swipe a bit
3878 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3879 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3880 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3881 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3882 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3883 .build());
3884
3885 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3886
3887 // End the swipe
3888 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3889 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3890 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3891 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3892 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3893 .build());
3894 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3895 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3896 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3897 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3898 .build());
3899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3900 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3901 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3902 .build());
3903
3904 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3905 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3906 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3907
3908 window->assertNoEvents();
3909}
3910
3911TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3913 sp<FakeWindowHandle> window =
3914 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3915 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003916 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003917
3918 // Start a three-finger touchpad swipe
3919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3920 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3921 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3922 .build());
3923 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3924 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3925 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3926 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3927 .build());
3928 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3929 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3930 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3931 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3932 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3933 .build());
3934
3935 // Move the swipe a bit
3936 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3937 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3938 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3939 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3940 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3941 .build());
3942
3943 // End the swipe
3944 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3945 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3946 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3947 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3948 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3949 .build());
3950 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3951 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3952 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3953 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3954 .build());
3955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3956 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3957 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3958 .build());
3959
3960 window->assertNoEvents();
3961}
3962
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003963/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003964 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3965 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003966 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003967 */
3968TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3970 sp<FakeWindowHandle> window =
3971 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3972 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003973 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003974
3975 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3977 .downTime(baseTime + 10)
3978 .eventTime(baseTime + 10)
3979 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3980 .build());
3981
3982 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3983
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003984 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003985 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003986
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003987 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003988
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003989 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3990 .downTime(baseTime + 10)
3991 .eventTime(baseTime + 30)
3992 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3993 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3994 .build());
3995
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003996 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3997
3998 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003999 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4000 .downTime(baseTime + 10)
4001 .eventTime(baseTime + 40)
4002 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4003 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4004 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004005
4006 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4007
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004008 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4009 .downTime(baseTime + 10)
4010 .eventTime(baseTime + 50)
4011 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4012 .build());
4013
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004014 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4015
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004016 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4017 .downTime(baseTime + 60)
4018 .eventTime(baseTime + 60)
4019 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4020 .build());
4021
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004022 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004023}
4024
4025/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004026 * Ensure the correct coordinate spaces are used by InputDispatcher.
4027 *
4028 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4029 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4030 * space.
4031 */
4032class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4033public:
4034 void SetUp() override {
4035 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004036 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004037 }
4038
4039 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4040 gui::DisplayInfo info;
4041 info.displayId = displayId;
4042 info.transform = transform;
4043 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004044 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004045 }
4046
4047 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4048 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004049 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004050 }
4051
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004052 void removeAllWindowsAndDisplays() {
4053 mDisplayInfos.clear();
4054 mWindowInfos.clear();
4055 }
4056
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004057 // Set up a test scenario where the display has a scaled projection and there are two windows
4058 // on the display.
4059 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4060 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4061 // respectively.
4062 ui::Transform displayTransform;
4063 displayTransform.set(2, 0, 0, 4);
4064 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4065
4066 std::shared_ptr<FakeApplicationHandle> application =
4067 std::make_shared<FakeApplicationHandle>();
4068
4069 // Add two windows to the display. Their frames are represented in the display space.
4070 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004071 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4072 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004073 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4074 addWindow(firstWindow);
4075
4076 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004077 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4078 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004079 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4080 addWindow(secondWindow);
4081 return {std::move(firstWindow), std::move(secondWindow)};
4082 }
4083
4084private:
4085 std::vector<gui::DisplayInfo> mDisplayInfos;
4086 std::vector<gui::WindowInfo> mWindowInfos;
4087};
4088
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004089TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004090 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4091 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004092 // selected so that if the hit test was performed with the point and the bounds being in
4093 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004094 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4095 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4096 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004097
4098 firstWindow->consumeMotionDown();
4099 secondWindow->assertNoEvents();
4100}
4101
4102// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4103// the event should be treated as being in the logical display space.
4104TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4105 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4106 // Send down to the first window. The point is represented in the logical display space. The
4107 // point is selected so that if the hit test was done in logical display space, then it would
4108 // end up in the incorrect window.
4109 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4110 PointF{75 * 2, 55 * 4});
4111
4112 firstWindow->consumeMotionDown();
4113 secondWindow->assertNoEvents();
4114}
4115
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004116// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4117// event should be treated as being in the logical display space.
4118TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4119 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4120
4121 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4122 ui::Transform injectedEventTransform;
4123 injectedEventTransform.set(matrix);
4124 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4125 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4126
4127 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4128 .displayId(ADISPLAY_ID_DEFAULT)
4129 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004130 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004131 .x(untransformedPoint.x)
4132 .y(untransformedPoint.y))
4133 .build();
4134 event.transform(matrix);
4135
4136 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4137 InputEventInjectionSync::WAIT_FOR_RESULT);
4138
4139 firstWindow->consumeMotionDown();
4140 secondWindow->assertNoEvents();
4141}
4142
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004143TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4144 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4145
4146 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004147 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4148 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4149 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004150
4151 firstWindow->assertNoEvents();
4152 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004153 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004154 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4155
4156 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4157 EXPECT_EQ(300, event->getRawX(0));
4158 EXPECT_EQ(880, event->getRawY(0));
4159
4160 // Ensure that the x and y values are in the window's coordinate space.
4161 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4162 // the logical display space. This will be the origin of the window space.
4163 EXPECT_EQ(100, event->getX(0));
4164 EXPECT_EQ(80, event->getY(0));
4165}
4166
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004167/** Ensure consistent behavior of InputDispatcher in all orientations. */
4168class InputDispatcherDisplayOrientationFixture
4169 : public InputDispatcherDisplayProjectionTest,
4170 public ::testing::WithParamInterface<ui::Rotation> {};
4171
4172// This test verifies the touchable region of a window for all rotations of the display by tapping
4173// in different locations on the display, specifically points close to the four corners of a
4174// window.
4175TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4176 constexpr static int32_t displayWidth = 400;
4177 constexpr static int32_t displayHeight = 800;
4178
4179 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4180
4181 const auto rotation = GetParam();
4182
4183 // Set up the display with the specified rotation.
4184 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4185 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4186 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4187 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4188 logicalDisplayWidth, logicalDisplayHeight);
4189 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4190
4191 // Create a window with its bounds determined in the logical display.
4192 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4193 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4194 sp<FakeWindowHandle> window =
4195 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4196 window->setFrame(frameInDisplay, displayTransform);
4197 addWindow(window);
4198
4199 // The following points in logical display space should be inside the window.
4200 static const std::array<vec2, 4> insidePoints{
4201 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4202 for (const auto pointInsideWindow : insidePoints) {
4203 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4204 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004205 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4206 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4207 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004208 window->consumeMotionDown();
4209
Prabir Pradhan678438e2023-04-13 19:32:51 +00004210 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4211 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4212 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004213 window->consumeMotionUp();
4214 }
4215
4216 // The following points in logical display space should be outside the window.
4217 static const std::array<vec2, 5> outsidePoints{
4218 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4219 for (const auto pointOutsideWindow : outsidePoints) {
4220 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4221 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004222 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4223 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4224 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004225
Prabir Pradhan678438e2023-04-13 19:32:51 +00004226 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4227 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4228 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004229 }
4230 window->assertNoEvents();
4231}
4232
4233// Run the precision tests for all rotations.
4234INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4235 InputDispatcherDisplayOrientationFixture,
4236 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4237 ui::ROTATION_270),
4238 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4239 return ftl::enum_string(testParamInfo.param);
4240 });
4241
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004242using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4243 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004244
4245class TransferTouchFixture : public InputDispatcherTest,
4246 public ::testing::WithParamInterface<TransferFunction> {};
4247
4248TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004249 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004250
4251 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004252 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004253 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4254 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004255 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004256 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004257 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4258 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004259 sp<FakeWindowHandle> wallpaper =
4260 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4261 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004262 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004263 mDispatcher->onWindowInfosChanged(
4264 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004265
4266 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004267 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4268 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004269
Svet Ganov5d3bc372020-01-26 23:11:07 -08004270 // Only the first window should get the down event
4271 firstWindow->consumeMotionDown();
4272 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004273 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004274
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004275 // Transfer touch to the second window
4276 TransferFunction f = GetParam();
4277 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4278 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004279 // The first window gets cancel and the second gets down
4280 firstWindow->consumeMotionCancel();
4281 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004282 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004283
4284 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004285 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4286 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004287 // The first window gets no events and the second gets up
4288 firstWindow->assertNoEvents();
4289 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004290 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004291}
4292
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004293/**
4294 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4295 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4296 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4297 * natural to the user.
4298 * In this test, we are sending a pointer to both spy window and first window. We then try to
4299 * transfer touch to the second window. The dispatcher should identify the first window as the
4300 * one that should lose the gesture, and therefore the action should be to move the gesture from
4301 * the first window to the second.
4302 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4303 * the other API, as well.
4304 */
4305TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4307
4308 // Create a couple of windows + a spy window
4309 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004310 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004311 spyWindow->setTrustedOverlay(true);
4312 spyWindow->setSpy(true);
4313 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004314 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004315 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004316 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004317
4318 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004319 mDispatcher->onWindowInfosChanged(
4320 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004321
4322 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004323 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4324 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004325 // Only the first window and spy should get the down event
4326 spyWindow->consumeMotionDown();
4327 firstWindow->consumeMotionDown();
4328
4329 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4330 // if f === 'transferTouch'.
4331 TransferFunction f = GetParam();
4332 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4333 ASSERT_TRUE(success);
4334 // The first window gets cancel and the second gets down
4335 firstWindow->consumeMotionCancel();
4336 secondWindow->consumeMotionDown();
4337
4338 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004339 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4340 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004341 // The first window gets no events and the second+spy get up
4342 firstWindow->assertNoEvents();
4343 spyWindow->consumeMotionUp();
4344 secondWindow->consumeMotionUp();
4345}
4346
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004347TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004348 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004349
4350 PointF touchPoint = {10, 10};
4351
4352 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004353 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004354 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4355 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004356 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004357 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004358 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4359 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004360 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004361
4362 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004363 mDispatcher->onWindowInfosChanged(
4364 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004365
4366 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004367 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4368 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4369 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004370 // Only the first window should get the down event
4371 firstWindow->consumeMotionDown();
4372 secondWindow->assertNoEvents();
4373
4374 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004375 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4376 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004377 // Only the first window should get the pointer down event
4378 firstWindow->consumeMotionPointerDown(1);
4379 secondWindow->assertNoEvents();
4380
4381 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004382 TransferFunction f = GetParam();
4383 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4384 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004385 // The first window gets cancel and the second gets down and pointer down
4386 firstWindow->consumeMotionCancel();
4387 secondWindow->consumeMotionDown();
4388 secondWindow->consumeMotionPointerDown(1);
4389
4390 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004391 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4392 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004393 // The first window gets nothing and the second gets pointer up
4394 firstWindow->assertNoEvents();
4395 secondWindow->consumeMotionPointerUp(1);
4396
4397 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004398 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4399 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004400 // The first window gets nothing and the second gets up
4401 firstWindow->assertNoEvents();
4402 secondWindow->consumeMotionUp();
4403}
4404
Arthur Hungc539dbb2022-12-08 07:45:36 +00004405TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4407
4408 // Create a couple of windows
4409 sp<FakeWindowHandle> firstWindow =
4410 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4411 ADISPLAY_ID_DEFAULT);
4412 firstWindow->setDupTouchToWallpaper(true);
4413 sp<FakeWindowHandle> secondWindow =
4414 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4415 ADISPLAY_ID_DEFAULT);
4416 secondWindow->setDupTouchToWallpaper(true);
4417
4418 sp<FakeWindowHandle> wallpaper1 =
4419 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4420 wallpaper1->setIsWallpaper(true);
4421
4422 sp<FakeWindowHandle> wallpaper2 =
4423 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4424 wallpaper2->setIsWallpaper(true);
4425 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004426 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4427 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4428 {},
4429 0,
4430 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004431
4432 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004433 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4434 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004435
4436 // Only the first window should get the down event
4437 firstWindow->consumeMotionDown();
4438 secondWindow->assertNoEvents();
4439 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4440 wallpaper2->assertNoEvents();
4441
4442 // Transfer touch focus to the second window
4443 TransferFunction f = GetParam();
4444 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4445 ASSERT_TRUE(success);
4446
4447 // The first window gets cancel and the second gets down
4448 firstWindow->consumeMotionCancel();
4449 secondWindow->consumeMotionDown();
4450 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4451 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4452
4453 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004454 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4455 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004456 // The first window gets no events and the second gets up
4457 firstWindow->assertNoEvents();
4458 secondWindow->consumeMotionUp();
4459 wallpaper1->assertNoEvents();
4460 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4461}
4462
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004463// For the cases of single pointer touch and two pointers non-split touch, the api's
4464// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4465// for the case where there are multiple pointers split across several windows.
4466INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4467 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004468 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4469 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004470 return dispatcher->transferTouch(destChannelToken,
4471 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004472 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004473 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4474 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004475 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004476 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004477 }));
4478
Svet Ganov5d3bc372020-01-26 23:11:07 -08004479TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004480 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004481
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004482 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004483 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4484 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004485 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004486
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004487 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004488 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4489 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004490 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004491
4492 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004493 mDispatcher->onWindowInfosChanged(
4494 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004495
4496 PointF pointInFirst = {300, 200};
4497 PointF pointInSecond = {300, 600};
4498
4499 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004500 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4501 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4502 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004503 // Only the first window should get the down event
4504 firstWindow->consumeMotionDown();
4505 secondWindow->assertNoEvents();
4506
4507 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004508 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4509 ADISPLAY_ID_DEFAULT,
4510 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004511 // The first window gets a move and the second a down
4512 firstWindow->consumeMotionMove();
4513 secondWindow->consumeMotionDown();
4514
4515 // Transfer touch focus to the second window
4516 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4517 // The first window gets cancel and the new gets pointer down (it already saw down)
4518 firstWindow->consumeMotionCancel();
4519 secondWindow->consumeMotionPointerDown(1);
4520
4521 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004522 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4523 ADISPLAY_ID_DEFAULT,
4524 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004525 // The first window gets nothing and the second gets pointer up
4526 firstWindow->assertNoEvents();
4527 secondWindow->consumeMotionPointerUp(1);
4528
4529 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004530 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4531 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004532 // The first window gets nothing and the second gets up
4533 firstWindow->assertNoEvents();
4534 secondWindow->consumeMotionUp();
4535}
4536
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004537// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4538// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4539// touch is not supported, so the touch should continue on those windows and the transferred-to
4540// window should get nothing.
4541TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4543
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004544 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004545 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4546 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004547 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004548
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004549 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004550 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4551 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004552 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004553
4554 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004555 mDispatcher->onWindowInfosChanged(
4556 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004557
4558 PointF pointInFirst = {300, 200};
4559 PointF pointInSecond = {300, 600};
4560
4561 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004562 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4563 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4564 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004565 // Only the first window should get the down event
4566 firstWindow->consumeMotionDown();
4567 secondWindow->assertNoEvents();
4568
4569 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004570 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4571 ADISPLAY_ID_DEFAULT,
4572 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004573 // The first window gets a move and the second a down
4574 firstWindow->consumeMotionMove();
4575 secondWindow->consumeMotionDown();
4576
4577 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004578 const bool transferred =
4579 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004580 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4581 ASSERT_FALSE(transferred);
4582 firstWindow->assertNoEvents();
4583 secondWindow->assertNoEvents();
4584
4585 // The rest of the dispatch should proceed as normal
4586 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004587 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4588 ADISPLAY_ID_DEFAULT,
4589 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004590 // The first window gets MOVE and the second gets pointer up
4591 firstWindow->consumeMotionMove();
4592 secondWindow->consumeMotionUp();
4593
4594 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004595 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4596 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004597 // The first window gets nothing and the second gets up
4598 firstWindow->consumeMotionUp();
4599 secondWindow->assertNoEvents();
4600}
4601
Arthur Hungabbb9d82021-09-01 14:52:30 +00004602// This case will create two windows and one mirrored window on the default display and mirror
4603// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4604// the windows info of second display before default display.
4605TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4607 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004608 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004609 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004610 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004611 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004612 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004613
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004614 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004615 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004616
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004617 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004618 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004619
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004620 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004621 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004622
4623 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004624 mDispatcher->onWindowInfosChanged(
4625 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4626 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4627 *secondWindowInPrimary->getInfo()},
4628 {},
4629 0,
4630 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004631
4632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4633 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4634 {50, 50}))
4635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4636
4637 // Window should receive motion event.
4638 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4639
4640 // Transfer touch focus
4641 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4642 secondWindowInPrimary->getToken()));
4643 // The first window gets cancel.
4644 firstWindowInPrimary->consumeMotionCancel();
4645 secondWindowInPrimary->consumeMotionDown();
4646
4647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4648 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4649 ADISPLAY_ID_DEFAULT, {150, 50}))
4650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4651 firstWindowInPrimary->assertNoEvents();
4652 secondWindowInPrimary->consumeMotionMove();
4653
4654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4655 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4656 {150, 50}))
4657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4658 firstWindowInPrimary->assertNoEvents();
4659 secondWindowInPrimary->consumeMotionUp();
4660}
4661
4662// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4663// 'transferTouch' api.
4664TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4666 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004667 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004668 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004669 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004670 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004671 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004672
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004673 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004674 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004675
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004676 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004677 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004678
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004679 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004680 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004681
4682 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004683 mDispatcher->onWindowInfosChanged(
4684 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4685 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4686 *secondWindowInPrimary->getInfo()},
4687 {},
4688 0,
4689 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004690
4691 // Touch on second display.
4692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4693 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4695
4696 // Window should receive motion event.
4697 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4698
4699 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004700 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004701
4702 // The first window gets cancel.
4703 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4704 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4705
4706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4707 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4708 SECOND_DISPLAY_ID, {150, 50}))
4709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4710 firstWindowInPrimary->assertNoEvents();
4711 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4712
4713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4714 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4716 firstWindowInPrimary->assertNoEvents();
4717 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4718}
4719
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004720TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4723 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004724
Vishnu Nair47074b82020-08-14 11:54:47 -07004725 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004726 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004727 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004728
4729 window->consumeFocusEvent(true);
4730
Prabir Pradhan678438e2023-04-13 19:32:51 +00004731 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004732
4733 // Window should receive key down event.
4734 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004735
4736 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004737 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004738 mFakePolicy->assertUserActivityPoked();
4739}
4740
4741TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4743 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4744 "Fake Window", ADISPLAY_ID_DEFAULT);
4745
4746 window->setDisableUserActivity(true);
4747 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004748 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004749 setFocusedWindow(window);
4750
4751 window->consumeFocusEvent(true);
4752
4753 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4754
4755 // Window should receive key down event.
4756 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4757
4758 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004759 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004760 mFakePolicy->assertUserActivityNotPoked();
4761}
4762
4763TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4765 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4766 "Fake Window", ADISPLAY_ID_DEFAULT);
4767
4768 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004769 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004770 setFocusedWindow(window);
4771
4772 window->consumeFocusEvent(true);
4773
4774 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4775 mDispatcher->waitForIdle();
4776
4777 // System key is not passed down
4778 window->assertNoEvents();
4779
4780 // Should have poked user activity
4781 mFakePolicy->assertUserActivityPoked();
4782}
4783
4784TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4787 "Fake Window", ADISPLAY_ID_DEFAULT);
4788
4789 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004790 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004791 setFocusedWindow(window);
4792
4793 window->consumeFocusEvent(true);
4794
4795 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4796 mDispatcher->waitForIdle();
4797
4798 // System key is not passed down
4799 window->assertNoEvents();
4800
4801 // Should have poked user activity
4802 mFakePolicy->assertUserActivityPoked();
4803}
4804
4805TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4807 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4808 "Fake Window", ADISPLAY_ID_DEFAULT);
4809
4810 window->setDisableUserActivity(true);
4811 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004812 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004813 setFocusedWindow(window);
4814
4815 window->consumeFocusEvent(true);
4816
4817 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4818 mDispatcher->waitForIdle();
4819
4820 // System key is not passed down
4821 window->assertNoEvents();
4822
4823 // Should have poked user activity
4824 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004825}
4826
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004827TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4829 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4830 "Fake Window", ADISPLAY_ID_DEFAULT);
4831
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004832 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004833
4834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4835 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4836 ADISPLAY_ID_DEFAULT, {100, 100}))
4837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4838
4839 window->consumeMotionEvent(
4840 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4841
4842 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004843 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004844 mFakePolicy->assertUserActivityPoked();
4845}
4846
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004847TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004849 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4850 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004851
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004852 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004853
Prabir Pradhan678438e2023-04-13 19:32:51 +00004854 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004855 mDispatcher->waitForIdle();
4856
4857 window->assertNoEvents();
4858}
4859
4860// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4861TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004863 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4864 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004865
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004866 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004867
4868 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004869 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004870 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004871 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4872 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004873
4874 // Window should receive only the motion event
4875 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4876 window->assertNoEvents(); // Key event or focus event will not be received
4877}
4878
arthurhungea3f4fc2020-12-21 23:18:53 +08004879TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4881
arthurhungea3f4fc2020-12-21 23:18:53 +08004882 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004883 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4884 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004885 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004886
arthurhungea3f4fc2020-12-21 23:18:53 +08004887 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004888 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4889 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004890 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004891
4892 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004893 mDispatcher->onWindowInfosChanged(
4894 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08004895
4896 PointF pointInFirst = {300, 200};
4897 PointF pointInSecond = {300, 600};
4898
4899 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004900 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4901 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4902 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004903 // Only the first window should get the down event
4904 firstWindow->consumeMotionDown();
4905 secondWindow->assertNoEvents();
4906
4907 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004908 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4909 ADISPLAY_ID_DEFAULT,
4910 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004911 // The first window gets a move and the second a down
4912 firstWindow->consumeMotionMove();
4913 secondWindow->consumeMotionDown();
4914
4915 // Send pointer cancel to the second window
4916 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004917 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004918 {pointInFirst, pointInSecond});
4919 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004920 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004921 // The first window gets move and the second gets cancel.
4922 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4923 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4924
4925 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004926 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4927 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004928 // The first window gets up and the second gets nothing.
4929 firstWindow->consumeMotionUp();
4930 secondWindow->assertNoEvents();
4931}
4932
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004933TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4935
4936 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004937 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004938 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004939 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4940 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4941 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4942
Harry Cutts33476232023-01-30 19:57:29 +00004943 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004944 window->assertNoEvents();
4945 mDispatcher->waitForIdle();
4946}
4947
chaviwd1c23182019-12-20 18:44:56 -08004948class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004949public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004950 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004951 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004952 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004953 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004954 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004955 }
4956
chaviwd1c23182019-12-20 18:44:56 -08004957 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4958
4959 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004960 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4961 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004962 }
4963
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004964 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4965
4966 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4967
chaviwd1c23182019-12-20 18:44:56 -08004968 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004969 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004970 expectedDisplayId, expectedFlags);
4971 }
4972
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004973 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004974 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004975 expectedDisplayId, expectedFlags);
4976 }
4977
chaviwd1c23182019-12-20 18:44:56 -08004978 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004979 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004980 expectedDisplayId, expectedFlags);
4981 }
4982
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004983 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004984 mInputReceiver->consumeMotionEvent(
4985 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4986 WithDisplayId(expectedDisplayId),
4987 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004988 }
4989
Arthur Hungfbfa5722021-11-16 02:45:54 +00004990 void consumeMotionPointerDown(int32_t pointerIdx) {
4991 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4992 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004993 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004994 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004995 }
4996
Evan Rosky84f07f02021-04-16 10:42:42 -07004997 MotionEvent* consumeMotion() {
4998 InputEvent* event = mInputReceiver->consume();
4999 if (!event) {
5000 ADD_FAILURE() << "No event was produced";
5001 return nullptr;
5002 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005003 if (event->getType() != InputEventType::MOTION) {
5004 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07005005 return nullptr;
5006 }
5007 return static_cast<MotionEvent*>(event);
5008 }
5009
chaviwd1c23182019-12-20 18:44:56 -08005010 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5011
5012private:
5013 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005014};
5015
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005016using InputDispatcherMonitorTest = InputDispatcherTest;
5017
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005018/**
5019 * Two entities that receive touch: A window, and a global monitor.
5020 * The touch goes to the window, and then the window disappears.
5021 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5022 * for the monitor, as well.
5023 * 1. foregroundWindow
5024 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5025 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005026TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5028 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005029 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005030
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005031 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005032
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005033 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5035 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5036 {100, 200}))
5037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5038
5039 // Both the foreground window and the global monitor should receive the touch down
5040 window->consumeMotionDown();
5041 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5042
5043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5044 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5045 ADISPLAY_ID_DEFAULT, {110, 200}))
5046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5047
5048 window->consumeMotionMove();
5049 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5050
5051 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005052 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005053 window->consumeMotionCancel();
5054 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5055
5056 // If more events come in, there will be no more foreground window to send them to. This will
5057 // cause a cancel for the monitor, as well.
5058 ASSERT_EQ(InputEventInjectionResult::FAILED,
5059 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5060 ADISPLAY_ID_DEFAULT, {120, 200}))
5061 << "Injection should fail because the window was removed";
5062 window->assertNoEvents();
5063 // Global monitor now gets the cancel
5064 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5065}
5066
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005067TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005069 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5070 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005071 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005072
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005073 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005074
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005076 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005078 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005079 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005080}
5081
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005082TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5083 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005084
Chris Yea209fde2020-07-22 13:54:51 -07005085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005086 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5087 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005088 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005089
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005091 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005093 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005094 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005095
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005096 // Pilfer pointers from the monitor.
5097 // This should not do anything and the window should continue to receive events.
5098 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005099
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005101 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5102 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005103 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005104
5105 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5106 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005107}
5108
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005109TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005111 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5112 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005113 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005114 window->setWindowOffset(20, 40);
5115 window->setWindowTransform(0, 1, -1, 0);
5116
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005117 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005118
5119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5120 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5121 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5122 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5123 MotionEvent* event = monitor.consumeMotion();
5124 // Even though window has transform, gesture monitor must not.
5125 ASSERT_EQ(ui::Transform(), event->getTransform());
5126}
5127
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005128TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005129 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005130 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005131
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005132 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005133 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005134 << "Injection should fail if there is a monitor, but no touchable window";
5135 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005136}
5137
chaviw81e2bb92019-12-18 15:03:51 -08005138TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005139 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005140 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5141 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005142
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005143 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005144
5145 NotifyMotionArgs motionArgs =
5146 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5147 ADISPLAY_ID_DEFAULT);
5148
Prabir Pradhan678438e2023-04-13 19:32:51 +00005149 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005150 // Window should receive motion down event.
5151 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5152
5153 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005154 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005155 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5156 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5157 motionArgs.pointerCoords[0].getX() - 10);
5158
Prabir Pradhan678438e2023-04-13 19:32:51 +00005159 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005160 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005161 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005162}
5163
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005164/**
5165 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5166 * the device default right away. In the test scenario, we check both the default value,
5167 * and the action of enabling / disabling.
5168 */
5169TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005171 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5172 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005173 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005174
5175 // Set focused application.
5176 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005177 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005178
5179 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005181 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005182 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005183
5184 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005185 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005186 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005187 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005188
5189 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005190 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005191 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005192 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005193 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005194 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005195 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005196 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005197
5198 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005199 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005201 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005202
5203 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005204 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005205 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005206 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005207 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005208 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005209 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005210 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005211
5212 window->assertNoEvents();
5213}
5214
Gang Wange9087892020-01-07 12:17:14 -05005215TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005216 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005217 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5218 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005219
5220 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005221 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005222
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005223 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005224 setFocusedWindow(window);
5225
Harry Cutts33476232023-01-30 19:57:29 +00005226 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005227
Prabir Pradhan678438e2023-04-13 19:32:51 +00005228 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5229 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005230
5231 InputEvent* event = window->consume();
5232 ASSERT_NE(event, nullptr);
5233
5234 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5235 ASSERT_NE(verified, nullptr);
5236 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5237
5238 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5239 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5240 ASSERT_EQ(keyArgs.source, verified->source);
5241 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5242
5243 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5244
5245 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005246 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005247 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005248 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5249 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5250 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5251 ASSERT_EQ(0, verifiedKey.repeatCount);
5252}
5253
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005254TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005256 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5257 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005258
5259 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5260
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005261 ui::Transform transform;
5262 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5263
5264 gui::DisplayInfo displayInfo;
5265 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5266 displayInfo.transform = transform;
5267
Patrick Williamsd828f302023-04-28 17:52:08 -05005268 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005269
Prabir Pradhan678438e2023-04-13 19:32:51 +00005270 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005271 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5272 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005273 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005274
5275 InputEvent* event = window->consume();
5276 ASSERT_NE(event, nullptr);
5277
5278 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5279 ASSERT_NE(verified, nullptr);
5280 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5281
5282 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5283 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5284 EXPECT_EQ(motionArgs.source, verified->source);
5285 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5286
5287 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5288
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005289 const vec2 rawXY =
5290 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5291 motionArgs.pointerCoords[0].getXYValue());
5292 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5293 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005294 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005295 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005296 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005297 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5298 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5299}
5300
chaviw09c8d2d2020-08-24 15:48:26 -07005301/**
5302 * Ensure that separate calls to sign the same data are generating the same key.
5303 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5304 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5305 * tests.
5306 */
5307TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5308 KeyEvent event = getTestKeyEvent();
5309 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5310
5311 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5312 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5313 ASSERT_EQ(hmac1, hmac2);
5314}
5315
5316/**
5317 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5318 */
5319TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5320 KeyEvent event = getTestKeyEvent();
5321 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5322 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5323
5324 verifiedEvent.deviceId += 1;
5325 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5326
5327 verifiedEvent.source += 1;
5328 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5329
5330 verifiedEvent.eventTimeNanos += 1;
5331 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5332
5333 verifiedEvent.displayId += 1;
5334 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5335
5336 verifiedEvent.action += 1;
5337 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5338
5339 verifiedEvent.downTimeNanos += 1;
5340 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5341
5342 verifiedEvent.flags += 1;
5343 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5344
5345 verifiedEvent.keyCode += 1;
5346 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5347
5348 verifiedEvent.scanCode += 1;
5349 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5350
5351 verifiedEvent.metaState += 1;
5352 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5353
5354 verifiedEvent.repeatCount += 1;
5355 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5356}
5357
Vishnu Nair958da932020-08-21 17:12:37 -07005358TEST_F(InputDispatcherTest, SetFocusedWindow) {
5359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5360 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005361 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005362 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005363 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5365
5366 // Top window is also focusable but is not granted focus.
5367 windowTop->setFocusable(true);
5368 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005369 mDispatcher->onWindowInfosChanged(
5370 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005371 setFocusedWindow(windowSecond);
5372
5373 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5375 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005376
5377 // Focused window should receive event.
5378 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5379 windowTop->assertNoEvents();
5380}
5381
5382TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5384 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005385 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005386 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5387
5388 window->setFocusable(true);
5389 // Release channel for window is no longer valid.
5390 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005392 setFocusedWindow(window);
5393
5394 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005395 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5396 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005397
5398 // window channel is invalid, so it should not receive any input event.
5399 window->assertNoEvents();
5400}
5401
5402TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5404 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005405 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005406 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005407 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5408
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005409 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005410 setFocusedWindow(window);
5411
5412 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005413 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5414 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005415
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005416 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005417 window->assertNoEvents();
5418}
5419
5420TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5422 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005423 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005424 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005425 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005426 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5427
5428 windowTop->setFocusable(true);
5429 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005430 mDispatcher->onWindowInfosChanged(
5431 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005432 setFocusedWindow(windowTop);
5433 windowTop->consumeFocusEvent(true);
5434
Chavi Weingarten847e8512023-03-29 00:26:09 +00005435 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005436 mDispatcher->onWindowInfosChanged(
5437 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005438 windowSecond->consumeFocusEvent(true);
5439 windowTop->consumeFocusEvent(false);
5440
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5442 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005443
5444 // Focused window should receive event.
5445 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5446}
5447
Chavi Weingarten847e8512023-03-29 00:26:09 +00005448TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5450 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005451 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005452 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005453 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005454 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5455
5456 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005457 windowSecond->setFocusable(false);
5458 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005459 mDispatcher->onWindowInfosChanged(
5460 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005461 setFocusedWindow(windowTop);
5462 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005463
Chavi Weingarten847e8512023-03-29 00:26:09 +00005464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5465 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005466
5467 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005468 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005469 windowSecond->assertNoEvents();
5470}
5471
5472TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5474 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005475 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005476 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005477 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5478 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005479 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5480
5481 window->setFocusable(true);
5482 previousFocusedWindow->setFocusable(true);
5483 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005484 mDispatcher->onWindowInfosChanged(
5485 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005486 setFocusedWindow(previousFocusedWindow);
5487 previousFocusedWindow->consumeFocusEvent(true);
5488
5489 // Requesting focus on invisible window takes focus from currently focused window.
5490 setFocusedWindow(window);
5491 previousFocusedWindow->consumeFocusEvent(false);
5492
5493 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005495 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5496 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005497
5498 // Window does not get focus event or key down.
5499 window->assertNoEvents();
5500
5501 // Window becomes visible.
5502 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005503 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005504
5505 // Window receives focus event.
5506 window->consumeFocusEvent(true);
5507 // Focused window receives key down.
5508 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5509}
5510
Vishnu Nair599f1412021-06-21 10:39:58 -07005511TEST_F(InputDispatcherTest, DisplayRemoved) {
5512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5513 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005514 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005515 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5516
5517 // window is granted focus.
5518 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005520 setFocusedWindow(window);
5521 window->consumeFocusEvent(true);
5522
5523 // When a display is removed window loses focus.
5524 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5525 window->consumeFocusEvent(false);
5526}
5527
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005528/**
5529 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5530 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5531 * of the 'slipperyEnterWindow'.
5532 *
5533 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5534 * a way so that the touched location is no longer covered by the top window.
5535 *
5536 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5537 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5538 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5539 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5540 * with ACTION_DOWN).
5541 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5542 * window moved itself away from the touched location and had Flag::SLIPPERY.
5543 *
5544 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5545 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5546 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5547 *
5548 * In this test, we ensure that the event received by the bottom window has
5549 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5550 */
5551TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005552 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005553 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005554
5555 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5556 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5557
5558 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005559 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005560 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005561 // Make sure this one overlaps the bottom window
5562 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5563 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5564 // one. Windows with the same owner are not considered to be occluding each other.
5565 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5566
5567 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005568 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005569 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5570
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005571 mDispatcher->onWindowInfosChanged(
5572 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005573
5574 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005575 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5576 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5577 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005578 slipperyExitWindow->consumeMotionDown();
5579 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005580 mDispatcher->onWindowInfosChanged(
5581 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005582
Prabir Pradhan678438e2023-04-13 19:32:51 +00005583 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5584 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5585 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005586
5587 slipperyExitWindow->consumeMotionCancel();
5588
5589 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5590 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5591}
5592
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005593/**
5594 * Two windows, one on the left and another on the right. The left window is slippery. The right
5595 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5596 * touch moves from the left window into the right window, the gesture should continue to go to the
5597 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5598 * reproduces a crash.
5599 */
5600TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5602
5603 sp<FakeWindowHandle> leftSlipperyWindow =
5604 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5605 leftSlipperyWindow->setSlippery(true);
5606 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5607
5608 sp<FakeWindowHandle> rightDropTouchesWindow =
5609 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5610 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5611 rightDropTouchesWindow->setDropInput(true);
5612
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005613 mDispatcher->onWindowInfosChanged(
5614 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005615
5616 // Start touch in the left window
5617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5618 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5619 .build());
5620 leftSlipperyWindow->consumeMotionDown();
5621
5622 // And move it into the right window
5623 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5624 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5625 .build());
5626
5627 // Since the right window isn't eligible to receive input, touch does not slip.
5628 // The left window continues to receive the gesture.
5629 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5630 rightDropTouchesWindow->assertNoEvents();
5631}
5632
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005633TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005634 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005635 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5636
5637 sp<FakeWindowHandle> leftWindow =
5638 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5639 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005640 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005641
5642 sp<FakeWindowHandle> rightSpy =
5643 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5644 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005645 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005646 rightSpy->setSpy(true);
5647 rightSpy->setTrustedOverlay(true);
5648
5649 sp<FakeWindowHandle> rightWindow =
5650 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5651 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005652 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005653
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005654 mDispatcher->onWindowInfosChanged(
5655 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005656
5657 // Touch in the left window
5658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5659 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5660 .build());
5661 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5662 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005663 ASSERT_NO_FATAL_FAILURE(
5664 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005665
5666 // Touch another finger over the right windows
5667 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5668 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5669 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5670 .build());
5671 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5672 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5673 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5674 mDispatcher->waitForIdle();
5675 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005676 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5677 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005678
5679 // Release finger over left window. The UP actions are not treated as device interaction.
5680 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5681 // is part of the UP action, we do not treat this as device interaction.
5682 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5683 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5684 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5685 .build());
5686 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5687 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5688 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5689 mDispatcher->waitForIdle();
5690 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5691
5692 // Move remaining finger
5693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5694 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5695 .build());
5696 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5697 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5698 mDispatcher->waitForIdle();
5699 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005700 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005701
5702 // Release all fingers
5703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5704 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5705 .build());
5706 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5707 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5708 mDispatcher->waitForIdle();
5709 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5710}
5711
5712TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5714
5715 sp<FakeWindowHandle> window =
5716 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5717 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005718 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005719
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005720 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005721 setFocusedWindow(window);
5722 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5723
5724 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5725 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5726 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005727 ASSERT_NO_FATAL_FAILURE(
5728 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005729
5730 // The UP actions are not treated as device interaction.
5731 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5732 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5733 mDispatcher->waitForIdle();
5734 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5735}
5736
Garfield Tan1c7bc862020-01-28 13:24:04 -08005737class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5738protected:
5739 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5740 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5741
Chris Yea209fde2020-07-22 13:54:51 -07005742 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005743 sp<FakeWindowHandle> mWindow;
5744
5745 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005746 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005747 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005748 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005749 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005750 ASSERT_EQ(OK, mDispatcher->start());
5751
5752 setUpWindow();
5753 }
5754
5755 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005756 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005757 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005758
Vishnu Nair47074b82020-08-14 11:54:47 -07005759 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005760 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005761 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005762 mWindow->consumeFocusEvent(true);
5763 }
5764
Chris Ye2ad95392020-09-01 13:44:44 -07005765 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005766 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005767 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005768 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005769 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005770
5771 // Window should receive key down event.
5772 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5773 }
5774
5775 void expectKeyRepeatOnce(int32_t repeatCount) {
5776 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5777 InputEvent* repeatEvent = mWindow->consume();
5778 ASSERT_NE(nullptr, repeatEvent);
5779
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005780 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005781
5782 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5783 uint32_t eventAction = repeatKeyEvent->getAction();
5784 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5785 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5786 }
5787
Chris Ye2ad95392020-09-01 13:44:44 -07005788 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005789 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005790 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005791 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005792 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005793
5794 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005795 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005796 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005797 }
5798};
5799
5800TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005801 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005802 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5803 expectKeyRepeatOnce(repeatCount);
5804 }
5805}
5806
5807TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005808 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005809 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5810 expectKeyRepeatOnce(repeatCount);
5811 }
Harry Cutts33476232023-01-30 19:57:29 +00005812 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005813 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005814 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5815 expectKeyRepeatOnce(repeatCount);
5816 }
5817}
5818
5819TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005820 sendAndConsumeKeyDown(/*deviceId=*/1);
5821 expectKeyRepeatOnce(/*repeatCount=*/1);
5822 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005823 mWindow->assertNoEvents();
5824}
5825
5826TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005827 sendAndConsumeKeyDown(/*deviceId=*/1);
5828 expectKeyRepeatOnce(/*repeatCount=*/1);
5829 sendAndConsumeKeyDown(/*deviceId=*/2);
5830 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005831 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005832 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005833 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005834 expectKeyRepeatOnce(/*repeatCount=*/2);
5835 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005836 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005837 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005838 mWindow->assertNoEvents();
5839}
5840
5841TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005842 sendAndConsumeKeyDown(/*deviceId=*/1);
5843 expectKeyRepeatOnce(/*repeatCount=*/1);
5844 sendAndConsumeKeyDown(/*deviceId=*/2);
5845 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005846 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005847 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005848 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005849 mWindow->assertNoEvents();
5850}
5851
liushenxiang42232912021-05-21 20:24:09 +08005852TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5853 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005854 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005855 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005856 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5857 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5858 mWindow->assertNoEvents();
5859}
5860
Garfield Tan1c7bc862020-01-28 13:24:04 -08005861TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005862 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005863 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005864 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5865 InputEvent* repeatEvent = mWindow->consume();
5866 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5867 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5868 IdGenerator::getSource(repeatEvent->getId()));
5869 }
5870}
5871
5872TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005873 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005874 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005875
5876 std::unordered_set<int32_t> idSet;
5877 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5878 InputEvent* repeatEvent = mWindow->consume();
5879 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5880 int32_t id = repeatEvent->getId();
5881 EXPECT_EQ(idSet.end(), idSet.find(id));
5882 idSet.insert(id);
5883 }
5884}
5885
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005886/* Test InputDispatcher for MultiDisplay */
5887class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5888public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005889 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005890 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005891
Chris Yea209fde2020-07-22 13:54:51 -07005892 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005893 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005894 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005895
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005896 // Set focus window for primary display, but focused display would be second one.
5897 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005898 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005899 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
5900
Vishnu Nair958da932020-08-21 17:12:37 -07005901 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005902 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005903
Chris Yea209fde2020-07-22 13:54:51 -07005904 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005905 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005906 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005907 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005908 // Set focus display to second one.
5909 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5910 // Set focus window for second display.
5911 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005912 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005913 mDispatcher->onWindowInfosChanged(
5914 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005915 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005916 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005917 }
5918
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005919 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005920 InputDispatcherTest::TearDown();
5921
Chris Yea209fde2020-07-22 13:54:51 -07005922 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005923 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005924 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005925 windowInSecondary.clear();
5926 }
5927
5928protected:
Chris Yea209fde2020-07-22 13:54:51 -07005929 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005930 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005931 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005932 sp<FakeWindowHandle> windowInSecondary;
5933};
5934
5935TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5936 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5938 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005940 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005941 windowInSecondary->assertNoEvents();
5942
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005943 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5945 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5946 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005947 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005948 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005949}
5950
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005951TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005952 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5954 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005955 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005956 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005957 windowInSecondary->assertNoEvents();
5958
5959 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005961 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005962 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005963 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005964
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005965 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005966 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08005967
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005968 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005969 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005970 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005971
5972 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005973 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005974 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005975 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005976 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005977 windowInSecondary->assertNoEvents();
5978}
5979
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005980// Test per-display input monitors for motion event.
5981TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005982 FakeMonitorReceiver monitorInPrimary =
5983 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5984 FakeMonitorReceiver monitorInSecondary =
5985 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005986
5987 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5989 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005991 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005992 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005993 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005994 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005995
5996 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5998 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006000 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006001 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006002 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006003 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006004
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006005 // Lift up the touch from the second display
6006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6007 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6009 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6010 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6011
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006012 // Test inject a non-pointer motion event.
6013 // If specific a display, it will dispatch to the focused window of particular display,
6014 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6016 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
6017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006018 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006019 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006020 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006021 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006022}
6023
6024// Test per-display input monitors for key event.
6025TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006026 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006027 FakeMonitorReceiver monitorInPrimary =
6028 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6029 FakeMonitorReceiver monitorInSecondary =
6030 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006031
6032 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6034 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006035 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006036 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006037 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006038 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006039}
6040
Vishnu Nair958da932020-08-21 17:12:37 -07006041TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6042 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006043 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006044 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006045 mDispatcher->onWindowInfosChanged(
6046 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6047 *windowInSecondary->getInfo()},
6048 {},
6049 0,
6050 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006051 setFocusedWindow(secondWindowInPrimary);
6052 windowInPrimary->consumeFocusEvent(false);
6053 secondWindowInPrimary->consumeFocusEvent(true);
6054
6055 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6057 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006058 windowInPrimary->assertNoEvents();
6059 windowInSecondary->assertNoEvents();
6060 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6061}
6062
Arthur Hungdfd528e2021-12-08 13:23:04 +00006063TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6064 FakeMonitorReceiver monitorInPrimary =
6065 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6066 FakeMonitorReceiver monitorInSecondary =
6067 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6068
6069 // Test touch down on primary display.
6070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6071 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6073 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6074 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6075
6076 // Test touch down on second display.
6077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6078 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6079 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6080 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6081 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6082
6083 // Trigger cancel touch.
6084 mDispatcher->cancelCurrentTouch();
6085 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6086 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6087 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6088 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6089
6090 // Test inject a move motion event, no window/monitor should receive the event.
6091 ASSERT_EQ(InputEventInjectionResult::FAILED,
6092 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6093 ADISPLAY_ID_DEFAULT, {110, 200}))
6094 << "Inject motion event should return InputEventInjectionResult::FAILED";
6095 windowInPrimary->assertNoEvents();
6096 monitorInPrimary.assertNoEvents();
6097
6098 ASSERT_EQ(InputEventInjectionResult::FAILED,
6099 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6100 SECOND_DISPLAY_ID, {110, 200}))
6101 << "Inject motion event should return InputEventInjectionResult::FAILED";
6102 windowInSecondary->assertNoEvents();
6103 monitorInSecondary.assertNoEvents();
6104}
6105
Jackal Guof9696682018-10-05 12:23:23 +08006106class InputFilterTest : public InputDispatcherTest {
6107protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006108 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6109 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006110 NotifyMotionArgs motionArgs;
6111
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006112 motionArgs =
6113 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006114 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006115 motionArgs =
6116 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006117 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006118 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006119 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006120 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006121 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006122 } else {
6123 mFakePolicy->assertFilterInputEventWasNotCalled();
6124 }
6125 }
6126
6127 void testNotifyKey(bool expectToBeFiltered) {
6128 NotifyKeyArgs keyArgs;
6129
6130 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006131 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006132 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006133 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006134 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006135
6136 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006137 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006138 } else {
6139 mFakePolicy->assertFilterInputEventWasNotCalled();
6140 }
6141 }
6142};
6143
6144// Test InputFilter for MotionEvent
6145TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6146 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006147 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6148 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006149
6150 // Enable InputFilter
6151 mDispatcher->setInputFilterEnabled(true);
6152 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006153 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6154 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006155
6156 // Disable InputFilter
6157 mDispatcher->setInputFilterEnabled(false);
6158 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006159 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6160 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006161}
6162
6163// Test InputFilter for KeyEvent
6164TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6165 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006166 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006167
6168 // Enable InputFilter
6169 mDispatcher->setInputFilterEnabled(true);
6170 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006171 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006172
6173 // Disable InputFilter
6174 mDispatcher->setInputFilterEnabled(false);
6175 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006176 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006177}
6178
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006179// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6180// logical display coordinate space.
6181TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6182 ui::Transform firstDisplayTransform;
6183 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6184 ui::Transform secondDisplayTransform;
6185 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6186
6187 std::vector<gui::DisplayInfo> displayInfos(2);
6188 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6189 displayInfos[0].transform = firstDisplayTransform;
6190 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6191 displayInfos[1].transform = secondDisplayTransform;
6192
Patrick Williamsd828f302023-04-28 17:52:08 -05006193 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006194
6195 // Enable InputFilter
6196 mDispatcher->setInputFilterEnabled(true);
6197
6198 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006199 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6200 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006201}
6202
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006203class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6204protected:
6205 virtual void SetUp() override {
6206 InputDispatcherTest::SetUp();
6207
6208 /**
6209 * We don't need to enable input filter to test the injected event policy, but we enabled it
6210 * here to make the tests more realistic, since this policy only matters when inputfilter is
6211 * on.
6212 */
6213 mDispatcher->setInputFilterEnabled(true);
6214
6215 std::shared_ptr<InputApplicationHandle> application =
6216 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006217 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6218 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006219
6220 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6221 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006222 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006223 setFocusedWindow(mWindow);
6224 mWindow->consumeFocusEvent(true);
6225 }
6226
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006227 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6228 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006229 KeyEvent event;
6230
6231 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6232 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6233 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006234 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006235 const int32_t additionalPolicyFlags =
6236 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006238 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006239 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006240 policyFlags | additionalPolicyFlags));
6241
6242 InputEvent* received = mWindow->consume();
6243 ASSERT_NE(nullptr, received);
6244 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006245 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006246 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6247 ASSERT_EQ(flags, keyEvent.getFlags());
6248 }
6249
6250 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6251 int32_t flags) {
6252 MotionEvent event;
6253 PointerProperties pointerProperties[1];
6254 PointerCoords pointerCoords[1];
6255 pointerProperties[0].clear();
6256 pointerProperties[0].id = 0;
6257 pointerCoords[0].clear();
6258 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6259 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6260
6261 ui::Transform identityTransform;
6262 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6263 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6264 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6265 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6266 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006267 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006268 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006269 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006270
6271 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006273 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006274 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006275 policyFlags | additionalPolicyFlags));
6276
6277 InputEvent* received = mWindow->consume();
6278 ASSERT_NE(nullptr, received);
6279 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006280 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006281 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6282 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006283 }
6284
6285private:
6286 sp<FakeWindowHandle> mWindow;
6287};
6288
6289TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006290 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6291 // filter. Without it, the event will no different from a regularly injected event, and the
6292 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006293 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6294 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006295}
6296
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006297TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006298 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006299 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006300 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6301}
6302
6303TEST_F(InputFilterInjectionPolicyTest,
6304 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6305 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006306 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006307 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006308}
6309
6310TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006311 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6312 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006313}
6314
chaviwfd6d3512019-03-25 13:23:49 -07006315class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006316 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006317 InputDispatcherTest::SetUp();
6318
Chris Yea209fde2020-07-22 13:54:51 -07006319 std::shared_ptr<FakeApplicationHandle> application =
6320 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006321 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006322 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006323 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006324
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006325 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006327 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006328
6329 // Set focused application.
6330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006331 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006332
6333 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006334 mDispatcher->onWindowInfosChanged(
6335 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006336 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006337 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006338 }
6339
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006340 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006341 InputDispatcherTest::TearDown();
6342
6343 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006344 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006345 }
6346
6347protected:
6348 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006349 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006350 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006351};
6352
6353// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6354// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6355// the onPointerDownOutsideFocus callback.
6356TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006358 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6359 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006361 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006362
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006363 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006364 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6365}
6366
6367// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6368// DOWN on the window that doesn't have focus. Ensure no window received the
6369// onPointerDownOutsideFocus callback.
6370TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006372 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006373 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006374 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006375
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006376 ASSERT_TRUE(mDispatcher->waitForIdle());
6377 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006378}
6379
6380// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6381// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6382TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6384 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006385 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006386 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006387
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006388 ASSERT_TRUE(mDispatcher->waitForIdle());
6389 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006390}
6391
6392// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6393// DOWN on the window that already has focus. Ensure no window received the
6394// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006395TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006397 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006398 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006399 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006400 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006401
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006402 ASSERT_TRUE(mDispatcher->waitForIdle());
6403 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006404}
6405
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006406// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6407// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6408TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6409 const MotionEvent event =
6410 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006413 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6414 .build();
6415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6416 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6417 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6418
6419 ASSERT_TRUE(mDispatcher->waitForIdle());
6420 mFakePolicy->assertOnPointerDownWasNotCalled();
6421 // Ensure that the unfocused window did not receive any FOCUS events.
6422 mUnfocusedWindow->assertNoEvents();
6423}
6424
chaviwaf87b3e2019-10-01 16:59:28 -07006425// These tests ensures we can send touch events to a single client when there are multiple input
6426// windows that point to the same client token.
6427class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6428 virtual void SetUp() override {
6429 InputDispatcherTest::SetUp();
6430
Chris Yea209fde2020-07-22 13:54:51 -07006431 std::shared_ptr<FakeApplicationHandle> application =
6432 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006433 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6434 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006435 mWindow1->setFrame(Rect(0, 0, 100, 100));
6436
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006437 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6438 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006439 mWindow2->setFrame(Rect(100, 100, 200, 200));
6440
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006441 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006442 }
6443
6444protected:
6445 sp<FakeWindowHandle> mWindow1;
6446 sp<FakeWindowHandle> mWindow2;
6447
6448 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006449 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006450 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6451 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006452 }
6453
6454 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6455 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006456 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006457 InputEvent* event = window->consume();
6458
6459 ASSERT_NE(nullptr, event) << name.c_str()
6460 << ": consumer should have returned non-NULL event.";
6461
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006462 ASSERT_EQ(InputEventType::MOTION, event->getType())
6463 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006464
6465 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006466 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006467 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006468
6469 for (size_t i = 0; i < points.size(); i++) {
6470 float expectedX = points[i].x;
6471 float expectedY = points[i].y;
6472
6473 EXPECT_EQ(expectedX, motionEvent.getX(i))
6474 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6475 << ", got " << motionEvent.getX(i);
6476 EXPECT_EQ(expectedY, motionEvent.getY(i))
6477 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6478 << ", got " << motionEvent.getY(i);
6479 }
6480 }
chaviw9eaa22c2020-07-01 16:21:27 -07006481
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006482 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006483 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006484 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6485 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006486
6487 // Always consume from window1 since it's the window that has the InputReceiver
6488 consumeMotionEvent(mWindow1, action, expectedPoints);
6489 }
chaviwaf87b3e2019-10-01 16:59:28 -07006490};
6491
6492TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6493 // Touch Window 1
6494 PointF touchedPoint = {10, 10};
6495 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006496 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006497
6498 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006499 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006500
6501 // Touch Window 2
6502 touchedPoint = {150, 150};
6503 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006504 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006505}
6506
chaviw9eaa22c2020-07-01 16:21:27 -07006507TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6508 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006509 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006510 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006511
6512 // Touch Window 1
6513 PointF touchedPoint = {10, 10};
6514 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006515 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006516 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006517 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006518
6519 // Touch Window 2
6520 touchedPoint = {150, 150};
6521 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006522 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6523 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006524
chaviw9eaa22c2020-07-01 16:21:27 -07006525 // Update the transform so rotation is set
6526 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006527 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006528 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6529 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006530}
6531
chaviw9eaa22c2020-07-01 16:21:27 -07006532TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006533 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006534 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006535
6536 // Touch Window 1
6537 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6538 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006539 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006540
6541 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006542 touchedPoints.push_back(PointF{150, 150});
6543 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006544 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006545
chaviw9eaa22c2020-07-01 16:21:27 -07006546 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006547 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006548 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006549
chaviw9eaa22c2020-07-01 16:21:27 -07006550 // Update the transform so rotation is set for Window 2
6551 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006552 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006553 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006554 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006555}
6556
chaviw9eaa22c2020-07-01 16:21:27 -07006557TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006558 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006559 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006560
6561 // Touch Window 1
6562 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6563 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006564 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006565
6566 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006567 touchedPoints.push_back(PointF{150, 150});
6568 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006569
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006570 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006571
6572 // Move both windows
6573 touchedPoints = {{20, 20}, {175, 175}};
6574 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6575 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6576
chaviw9eaa22c2020-07-01 16:21:27 -07006577 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006578
chaviw9eaa22c2020-07-01 16:21:27 -07006579 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006580 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006581 expectedPoints.pop_back();
6582
6583 // Touch Window 2
6584 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006585 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006586 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006587 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006588
6589 // Move both windows
6590 touchedPoints = {{20, 20}, {175, 175}};
6591 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6592 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6593
6594 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006595}
6596
6597TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6598 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006599 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006600
6601 // Touch Window 1
6602 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6603 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006604 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006605
6606 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006607 touchedPoints.push_back(PointF{150, 150});
6608 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006609
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006610 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006611
6612 // Move both windows
6613 touchedPoints = {{20, 20}, {175, 175}};
6614 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6615 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6616
chaviw9eaa22c2020-07-01 16:21:27 -07006617 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006618}
6619
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006620/**
6621 * When one of the windows is slippery, the touch should not slip into the other window with the
6622 * same input channel.
6623 */
6624TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6625 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006626 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006627
6628 // Touch down in window 1
6629 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6630 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6631 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6632
6633 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6634 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6635 // getting generated.
6636 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6637 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6638
6639 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6640}
6641
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006642/**
6643 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6644 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6645 * that the pointer is hovering over may have a different transform.
6646 */
6647TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006648 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006649
6650 // Start hover in window 1
6651 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6652 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6653 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6654 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6655
6656 // Move hover to window 2.
6657 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6658 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6659
6660 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6661 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6662 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6663}
6664
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006665class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6666 virtual void SetUp() override {
6667 InputDispatcherTest::SetUp();
6668
Chris Yea209fde2020-07-22 13:54:51 -07006669 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006670 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006671 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6672 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006673 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006674 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006675 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006676
6677 // Set focused application.
6678 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6679
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006680 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006681 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006682 mWindow->consumeFocusEvent(true);
6683 }
6684
6685 virtual void TearDown() override {
6686 InputDispatcherTest::TearDown();
6687 mWindow.clear();
6688 }
6689
6690protected:
Chris Yea209fde2020-07-22 13:54:51 -07006691 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006692 sp<FakeWindowHandle> mWindow;
6693 static constexpr PointF WINDOW_LOCATION = {20, 20};
6694
6695 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006697 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6698 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006700 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6701 WINDOW_LOCATION));
6702 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006703
6704 sp<FakeWindowHandle> addSpyWindow() {
6705 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006706 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006707 spy->setTrustedOverlay(true);
6708 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006709 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006710 spy->setDispatchingTimeout(30ms);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006711 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006712 return spy;
6713 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006714};
6715
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006716// Send a tap and respond, which should not cause an ANR.
6717TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6718 tapOnWindow();
6719 mWindow->consumeMotionDown();
6720 mWindow->consumeMotionUp();
6721 ASSERT_TRUE(mDispatcher->waitForIdle());
6722 mFakePolicy->assertNotifyAnrWasNotCalled();
6723}
6724
6725// Send a regular key and respond, which should not cause an ANR.
6726TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006728 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6729 ASSERT_TRUE(mDispatcher->waitForIdle());
6730 mFakePolicy->assertNotifyAnrWasNotCalled();
6731}
6732
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006733TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6734 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006735 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006736 mWindow->consumeFocusEvent(false);
6737
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006738 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006739 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006740 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms,
Harry Cutts33476232023-01-30 19:57:29 +00006741 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006743 // Key will not go to window because we have no focused window.
6744 // The 'no focused window' ANR timer should start instead.
6745
6746 // Now, the focused application goes away.
6747 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6748 // The key should get dropped and there should be no ANR.
6749
6750 ASSERT_TRUE(mDispatcher->waitForIdle());
6751 mFakePolicy->assertNotifyAnrWasNotCalled();
6752}
6753
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006754// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006755// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6756// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006757TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006759 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6760 WINDOW_LOCATION));
6761
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006762 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6763 ASSERT_TRUE(sequenceNum);
6764 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006765 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006766
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006767 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006768 mWindow->consumeMotionEvent(
6769 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006770 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006771 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006772}
6773
6774// Send a key to the app and have the app not respond right away.
6775TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6776 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006778 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6779 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006780 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006781 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006782 ASSERT_TRUE(mDispatcher->waitForIdle());
6783}
6784
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006785// We have a focused application, but no focused window
6786TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006787 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006788 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006789 mWindow->consumeFocusEvent(false);
6790
6791 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006793 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6794 WINDOW_LOCATION));
6795 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6796 mDispatcher->waitForIdle();
6797 mFakePolicy->assertNotifyAnrWasNotCalled();
6798
6799 // Once a focused event arrives, we get an ANR for this application
6800 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6801 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006802 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006803 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006804 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006805 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006807 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006808 ASSERT_TRUE(mDispatcher->waitForIdle());
6809}
6810
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006811/**
6812 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6813 * there will not be an ANR.
6814 */
6815TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6816 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006817 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006818 mWindow->consumeFocusEvent(false);
6819
6820 KeyEvent event;
6821 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6822 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6823
6824 // Define a valid key down event that is stale (too old).
6825 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006826 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006827 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006828
6829 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6830
6831 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006832 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006833 InputEventInjectionSync::WAIT_FOR_RESULT,
6834 INJECT_EVENT_TIMEOUT, policyFlags);
6835 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6836 << "Injection should fail because the event is stale";
6837
6838 ASSERT_TRUE(mDispatcher->waitForIdle());
6839 mFakePolicy->assertNotifyAnrWasNotCalled();
6840 mWindow->assertNoEvents();
6841}
6842
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006843// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006844// Make sure that we don't notify policy twice about the same ANR.
6845TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006846 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006847 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006848 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006849
6850 // Once a focused event arrives, we get an ANR for this application
6851 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6852 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006853 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006854 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006855 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006856 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006857 const std::chrono::duration appTimeout =
6858 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6859 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006860
Vishnu Naire4df8752022-09-08 09:17:55 -07006861 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006862 // ANR should not be raised again. It is up to policy to do that if it desires.
6863 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006864
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006865 // If we now get a focused window, the ANR should stop, but the policy handles that via
6866 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006867 ASSERT_TRUE(mDispatcher->waitForIdle());
6868}
6869
6870// We have a focused application, but no focused window
6871TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006872 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006873 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006874 mWindow->consumeFocusEvent(false);
6875
6876 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006877 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006878 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006879 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006880 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006881
Vishnu Naire4df8752022-09-08 09:17:55 -07006882 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6883 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884
6885 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006886 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006887 ASSERT_TRUE(mDispatcher->waitForIdle());
6888 mWindow->assertNoEvents();
6889}
6890
6891/**
6892 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6893 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6894 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6895 * the ANR mechanism should still work.
6896 *
6897 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6898 * DOWN event, while not responding on the second one.
6899 */
6900TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6901 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6902 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6903 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6904 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6905 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006906 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006907
6908 // Now send ACTION_UP, with identical timestamp
6909 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6910 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6911 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6912 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006913 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914
6915 // We have now sent down and up. Let's consume first event and then ANR on the second.
6916 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6917 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006918 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006919}
6920
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006921// A spy window can receive an ANR
6922TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6923 sp<FakeWindowHandle> spy = addSpyWindow();
6924
6925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6926 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6927 WINDOW_LOCATION));
6928 mWindow->consumeMotionDown();
6929
6930 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6931 ASSERT_TRUE(sequenceNum);
6932 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006933 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006934
6935 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006936 spy->consumeMotionEvent(
6937 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006938 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006939 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006940}
6941
6942// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006943// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006944TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6945 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006946
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6948 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006949 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006951
6952 // Stuck on the ACTION_UP
6953 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006954 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006955
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006956 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006957 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006958 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6959 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006960
6961 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6962 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006963 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006964 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006965 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006966}
6967
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006968// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006969// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006970TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6971 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006972
6973 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006974 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6975 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006976
6977 mWindow->consumeMotionDown();
6978 // Stuck on the ACTION_UP
6979 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006980 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006981
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006982 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006983 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006984 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6985 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006986
6987 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6988 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006989 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006990 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006991 spy->assertNoEvents();
6992}
6993
6994TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6995 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6996
6997 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6998
6999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7000 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7001 WINDOW_LOCATION));
7002
7003 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7004 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7005 ASSERT_TRUE(consumeSeq);
7006
Prabir Pradhanedd96402022-02-15 01:46:16 -08007007 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007008
7009 monitor.finishEvent(*consumeSeq);
7010 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7011
7012 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007013 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007014}
7015
7016// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7017// process events, you don't get an anr. When the window later becomes unresponsive again, you
7018// get an ANR again.
7019// 1. tap -> block on ACTION_UP -> receive ANR
7020// 2. consume all pending events (= queue becomes healthy again)
7021// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7022TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7023 tapOnWindow();
7024
7025 mWindow->consumeMotionDown();
7026 // Block on ACTION_UP
7027 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007028 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007029 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7030 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007031 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007032 mWindow->assertNoEvents();
7033
7034 tapOnWindow();
7035 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007036 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007037 mWindow->consumeMotionUp();
7038
7039 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007040 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007041 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007042 mWindow->assertNoEvents();
7043}
7044
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007045// If a connection remains unresponsive for a while, make sure policy is only notified once about
7046// it.
7047TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7050 WINDOW_LOCATION));
7051
7052 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007053 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007054 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007055 // 'notifyConnectionUnresponsive' should only be called once per connection
7056 mFakePolicy->assertNotifyAnrWasNotCalled();
7057 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007058 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007059 mWindow->consumeMotionEvent(
7060 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007061 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007062 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007063 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007064 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007065}
7066
7067/**
7068 * If a window is processing a motion event, and then a key event comes in, the key event should
7069 * not to to the focused window until the motion is processed.
7070 *
7071 * Warning!!!
7072 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7073 * and the injection timeout that we specify when injecting the key.
7074 * We must have the injection timeout (10ms) be smaller than
7075 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7076 *
7077 * If that value changes, this test should also change.
7078 */
7079TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7080 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007081 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007082
7083 tapOnWindow();
7084 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7085 ASSERT_TRUE(downSequenceNum);
7086 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7087 ASSERT_TRUE(upSequenceNum);
7088 // Don't finish the events yet, and send a key
7089 // Injection will "succeed" because we will eventually give up and send the key to the focused
7090 // window even if motions are still being processed. But because the injection timeout is short,
7091 // we will receive INJECTION_TIMED_OUT as the result.
7092
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007093 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007094 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007095 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007096 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007097 // Key will not be sent to the window, yet, because the window is still processing events
7098 // and the key remains pending, waiting for the touch events to be processed
7099 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7100 ASSERT_FALSE(keySequenceNum);
7101
7102 std::this_thread::sleep_for(500ms);
7103 // if we wait long enough though, dispatcher will give up, and still send the key
7104 // to the focused window, even though we have not yet finished the motion event
7105 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7106 mWindow->finishEvent(*downSequenceNum);
7107 mWindow->finishEvent(*upSequenceNum);
7108}
7109
7110/**
7111 * If a window is processing a motion event, and then a key event comes in, the key event should
7112 * not go to the focused window until the motion is processed.
7113 * If then a new motion comes in, then the pending key event should be going to the currently
7114 * focused window right away.
7115 */
7116TEST_F(InputDispatcherSingleWindowAnr,
7117 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7118 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007119 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007120
7121 tapOnWindow();
7122 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7123 ASSERT_TRUE(downSequenceNum);
7124 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7125 ASSERT_TRUE(upSequenceNum);
7126 // Don't finish the events yet, and send a key
7127 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007129 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7130 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007131 // At this point, key is still pending, and should not be sent to the application yet.
7132 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7133 ASSERT_FALSE(keySequenceNum);
7134
7135 // Now tap down again. It should cause the pending key to go to the focused window right away.
7136 tapOnWindow();
7137 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7138 // the other events yet. We can finish events in any order.
7139 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7140 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7141 mWindow->consumeMotionDown();
7142 mWindow->consumeMotionUp();
7143 mWindow->assertNoEvents();
7144}
7145
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007146/**
7147 * Send an event to the app and have the app not respond right away.
7148 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7149 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7150 * At some point, the window becomes responsive again.
7151 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7152 */
7153TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7155 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7156 .build());
7157
7158 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7159 ASSERT_TRUE(sequenceNum);
7160 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7161 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7162
7163 mWindow->finishEvent(*sequenceNum);
7164 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7165 ASSERT_TRUE(mDispatcher->waitForIdle());
7166 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7167
7168 // Now that the window is responsive, let's continue the gesture.
7169 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7170 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7171 .build());
7172
7173 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7174 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7175 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7176 .build());
7177
7178 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7179 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7180 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7181 .build());
7182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7183 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7184 .build());
7185 // We already canceled this pointer, so the window shouldn't get any new events.
7186 mWindow->assertNoEvents();
7187
7188 // Start another one.
7189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7190 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7191 .build());
7192 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7193}
7194
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007195class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7196 virtual void SetUp() override {
7197 InputDispatcherTest::SetUp();
7198
Chris Yea209fde2020-07-22 13:54:51 -07007199 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007200 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007201 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7202 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007203 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007204 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007205 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007206
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007207 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7208 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007209 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007210 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007211
7212 // Set focused application.
7213 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007214 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007215
7216 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007217 mDispatcher->onWindowInfosChanged(
7218 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007219 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007220 mFocusedWindow->consumeFocusEvent(true);
7221 }
7222
7223 virtual void TearDown() override {
7224 InputDispatcherTest::TearDown();
7225
7226 mUnfocusedWindow.clear();
7227 mFocusedWindow.clear();
7228 }
7229
7230protected:
Chris Yea209fde2020-07-22 13:54:51 -07007231 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007232 sp<FakeWindowHandle> mUnfocusedWindow;
7233 sp<FakeWindowHandle> mFocusedWindow;
7234 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7235 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7236 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7237
7238 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7239
7240 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7241
7242private:
7243 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007245 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7246 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007248 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7249 location));
7250 }
7251};
7252
7253// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7254// should be ANR'd first.
7255TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007257 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7258 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007260 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007261 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007262 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007263 // We consumed all events, so no ANR
7264 ASSERT_TRUE(mDispatcher->waitForIdle());
7265 mFakePolicy->assertNotifyAnrWasNotCalled();
7266
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007268 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7269 FOCUSED_WINDOW_LOCATION));
7270 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7271 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007272
7273 const std::chrono::duration timeout =
7274 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007275 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007276 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7277 // sequence to make it consistent
7278 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007280 mFocusedWindow->consumeMotionDown();
7281 // This cancel is generated because the connection was unresponsive
7282 mFocusedWindow->consumeMotionCancel();
7283 mFocusedWindow->assertNoEvents();
7284 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007285 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007286 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7287 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007288 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007289}
7290
7291// If we have 2 windows with identical timeouts that are both unresponsive,
7292// it doesn't matter which order they should have ANR.
7293// But we should receive ANR for both.
7294TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7295 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007296 mUnfocusedWindow->setDispatchingTimeout(
7297 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007298 mDispatcher->onWindowInfosChanged(
7299 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007300
7301 tapOnFocusedWindow();
7302 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007303 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007304 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7305 mFocusedWindow->getDispatchingTimeout(
7306 DISPATCHING_TIMEOUT)),
7307 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7308
7309 ASSERT_THAT(anrConnectionTokens,
7310 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7311 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007312
7313 ASSERT_TRUE(mDispatcher->waitForIdle());
7314 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007315
7316 mFocusedWindow->consumeMotionDown();
7317 mFocusedWindow->consumeMotionUp();
7318 mUnfocusedWindow->consumeMotionOutside();
7319
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007320 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7321 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007322
7323 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007324 ASSERT_THAT(responsiveTokens,
7325 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7326 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007327 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007328}
7329
7330// If a window is already not responding, the second tap on the same window should be ignored.
7331// We should also log an error to account for the dropped event (not tested here).
7332// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7333TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7334 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007335 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007336 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007337 // Receive the events, but don't respond
7338 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7339 ASSERT_TRUE(downEventSequenceNum);
7340 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7341 ASSERT_TRUE(upEventSequenceNum);
7342 const std::chrono::duration timeout =
7343 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007344 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007345
7346 // Tap once again
7347 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007348 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007349 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7350 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007351 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007352 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7353 FOCUSED_WINDOW_LOCATION));
7354 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7355 // valid touch target
7356 mUnfocusedWindow->assertNoEvents();
7357
7358 // Consume the first tap
7359 mFocusedWindow->finishEvent(*downEventSequenceNum);
7360 mFocusedWindow->finishEvent(*upEventSequenceNum);
7361 ASSERT_TRUE(mDispatcher->waitForIdle());
7362 // The second tap did not go to the focused window
7363 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007364 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007365 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7366 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007367 mFakePolicy->assertNotifyAnrWasNotCalled();
7368}
7369
7370// If you tap outside of all windows, there will not be ANR
7371TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007372 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007373 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7374 LOCATION_OUTSIDE_ALL_WINDOWS));
7375 ASSERT_TRUE(mDispatcher->waitForIdle());
7376 mFakePolicy->assertNotifyAnrWasNotCalled();
7377}
7378
7379// Since the focused window is paused, tapping on it should not produce any events
7380TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7381 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007382 mDispatcher->onWindowInfosChanged(
7383 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007384
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007385 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007386 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7387 FOCUSED_WINDOW_LOCATION));
7388
7389 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7390 ASSERT_TRUE(mDispatcher->waitForIdle());
7391 // Should not ANR because the window is paused, and touches shouldn't go to it
7392 mFakePolicy->assertNotifyAnrWasNotCalled();
7393
7394 mFocusedWindow->assertNoEvents();
7395 mUnfocusedWindow->assertNoEvents();
7396}
7397
7398/**
7399 * If a window is processing a motion event, and then a key event comes in, the key event should
7400 * not to to the focused window until the motion is processed.
7401 * If a different window becomes focused at this time, the key should go to that window instead.
7402 *
7403 * Warning!!!
7404 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7405 * and the injection timeout that we specify when injecting the key.
7406 * We must have the injection timeout (10ms) be smaller than
7407 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7408 *
7409 * If that value changes, this test should also change.
7410 */
7411TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7412 // Set a long ANR timeout to prevent it from triggering
7413 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007414 mDispatcher->onWindowInfosChanged(
7415 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007416
7417 tapOnUnfocusedWindow();
7418 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7419 ASSERT_TRUE(downSequenceNum);
7420 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7421 ASSERT_TRUE(upSequenceNum);
7422 // Don't finish the events yet, and send a key
7423 // Injection will succeed because we will eventually give up and send the key to the focused
7424 // window even if motions are still being processed.
7425
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007426 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007427 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007428 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007430 // Key will not be sent to the window, yet, because the window is still processing events
7431 // and the key remains pending, waiting for the touch events to be processed
7432 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7433 ASSERT_FALSE(keySequenceNum);
7434
7435 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007436 mFocusedWindow->setFocusable(false);
7437 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007438 mDispatcher->onWindowInfosChanged(
7439 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007440 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007441
7442 // Focus events should precede the key events
7443 mUnfocusedWindow->consumeFocusEvent(true);
7444 mFocusedWindow->consumeFocusEvent(false);
7445
7446 // Finish the tap events, which should unblock dispatcher
7447 mUnfocusedWindow->finishEvent(*downSequenceNum);
7448 mUnfocusedWindow->finishEvent(*upSequenceNum);
7449
7450 // Now that all queues are cleared and no backlog in the connections, the key event
7451 // can finally go to the newly focused "mUnfocusedWindow".
7452 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7453 mFocusedWindow->assertNoEvents();
7454 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007455 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007456}
7457
7458// When the touch stream is split across 2 windows, and one of them does not respond,
7459// then ANR should be raised and the touch should be canceled for the unresponsive window.
7460// The other window should not be affected by that.
7461TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7462 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007463 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7464 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7465 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007466 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007467 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007468
7469 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007470 mDispatcher->notifyMotion(
7471 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7472 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007473
7474 const std::chrono::duration timeout =
7475 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007476 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007477
7478 mUnfocusedWindow->consumeMotionDown();
7479 mFocusedWindow->consumeMotionDown();
7480 // Focused window may or may not receive ACTION_MOVE
7481 // But it should definitely receive ACTION_CANCEL due to the ANR
7482 InputEvent* event;
7483 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7484 ASSERT_TRUE(moveOrCancelSequenceNum);
7485 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7486 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007487 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007488 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7489 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7490 mFocusedWindow->consumeMotionCancel();
7491 } else {
7492 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7493 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007494 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007495 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7496 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007497
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007498 mUnfocusedWindow->assertNoEvents();
7499 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007500 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007501}
7502
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007503/**
7504 * If we have no focused window, and a key comes in, we start the ANR timer.
7505 * The focused application should add a focused window before the timer runs out to prevent ANR.
7506 *
7507 * If the user touches another application during this time, the key should be dropped.
7508 * Next, if a new focused window comes in, without toggling the focused application,
7509 * then no ANR should occur.
7510 *
7511 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7512 * but in some cases the policy may not update the focused application.
7513 */
7514TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7515 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7516 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007517 focusedApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007518 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7519 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7520 mFocusedWindow->setFocusable(false);
7521
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007522 mDispatcher->onWindowInfosChanged(
7523 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007524 mFocusedWindow->consumeFocusEvent(false);
7525
7526 // Send a key. The ANR timer should start because there is no focused window.
7527 // 'focusedApplication' will get blamed if this timer completes.
7528 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007529 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007530 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007531 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms,
Harry Cutts33476232023-01-30 19:57:29 +00007532 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007534
7535 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7536 // then the injected touches won't cause the focused event to get dropped.
7537 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7538 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7539 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7540 // For this test, it means that the key would get delivered to the window once it becomes
7541 // focused.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007542 std::this_thread::sleep_for(50ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007543
7544 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7547 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007548
7549 // We do not consume the motion right away, because that would require dispatcher to first
7550 // process (== drop) the key event, and by that time, ANR will be raised.
7551 // Set the focused window first.
7552 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007553 mDispatcher->onWindowInfosChanged(
7554 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007555 setFocusedWindow(mFocusedWindow);
7556 mFocusedWindow->consumeFocusEvent(true);
7557 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7558 // to another application. This could be a bug / behaviour in the policy.
7559
7560 mUnfocusedWindow->consumeMotionDown();
7561
7562 ASSERT_TRUE(mDispatcher->waitForIdle());
7563 // Should not ANR because we actually have a focused window. It was just added too slowly.
7564 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7565}
7566
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007567// These tests ensure we cannot send touch events to a window that's positioned behind a window
7568// that has feature NO_INPUT_CHANNEL.
7569// Layout:
7570// Top (closest to user)
7571// mNoInputWindow (above all windows)
7572// mBottomWindow
7573// Bottom (furthest from user)
7574class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7575 virtual void SetUp() override {
7576 InputDispatcherTest::SetUp();
7577
7578 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007579 mNoInputWindow =
7580 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7581 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007582 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007583 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007584 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7585 // It's perfectly valid for this window to not have an associated input channel
7586
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007587 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7588 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007589 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7590
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007591 mDispatcher->onWindowInfosChanged(
7592 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007593 }
7594
7595protected:
7596 std::shared_ptr<FakeApplicationHandle> mApplication;
7597 sp<FakeWindowHandle> mNoInputWindow;
7598 sp<FakeWindowHandle> mBottomWindow;
7599};
7600
7601TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7602 PointF touchedPoint = {10, 10};
7603
Prabir Pradhan678438e2023-04-13 19:32:51 +00007604 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7605 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7606 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007607
7608 mNoInputWindow->assertNoEvents();
7609 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7610 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7611 // and therefore should prevent mBottomWindow from receiving touches
7612 mBottomWindow->assertNoEvents();
7613}
7614
7615/**
7616 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7617 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7618 */
7619TEST_F(InputDispatcherMultiWindowOcclusionTests,
7620 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007621 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7622 "Window with input channel and NO_INPUT_CHANNEL",
7623 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007624
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007625 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007626 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007627 mDispatcher->onWindowInfosChanged(
7628 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007629
7630 PointF touchedPoint = {10, 10};
7631
Prabir Pradhan678438e2023-04-13 19:32:51 +00007632 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7633 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7634 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007635
7636 mNoInputWindow->assertNoEvents();
7637 mBottomWindow->assertNoEvents();
7638}
7639
Vishnu Nair958da932020-08-21 17:12:37 -07007640class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7641protected:
7642 std::shared_ptr<FakeApplicationHandle> mApp;
7643 sp<FakeWindowHandle> mWindow;
7644 sp<FakeWindowHandle> mMirror;
7645
7646 virtual void SetUp() override {
7647 InputDispatcherTest::SetUp();
7648 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007649 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7650 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7651 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007652 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7653 mWindow->setFocusable(true);
7654 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007655 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007656 }
7657};
7658
7659TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7660 // Request focus on a mirrored window
7661 setFocusedWindow(mMirror);
7662
7663 // window gets focused
7664 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7666 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007667 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7668}
7669
7670// A focused & mirrored window remains focused only if the window and its mirror are both
7671// focusable.
7672TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7673 setFocusedWindow(mMirror);
7674
7675 // window gets focused
7676 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7678 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007679 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7681 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007682 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7683
7684 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007685 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007686
7687 // window loses focus since one of the windows associated with the token in not focusable
7688 mWindow->consumeFocusEvent(false);
7689
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007690 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7691 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007692 mWindow->assertNoEvents();
7693}
7694
7695// A focused & mirrored window remains focused until the window and its mirror both become
7696// invisible.
7697TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7698 setFocusedWindow(mMirror);
7699
7700 // window gets focused
7701 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7703 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007704 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7706 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007707 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7708
7709 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007710 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007711
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7713 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007714 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7716 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007717 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7718
7719 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007720 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007721
7722 // window loses focus only after all windows associated with the token become invisible.
7723 mWindow->consumeFocusEvent(false);
7724
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007725 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7726 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007727 mWindow->assertNoEvents();
7728}
7729
7730// A focused & mirrored window remains focused until both windows are removed.
7731TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7732 setFocusedWindow(mMirror);
7733
7734 // window gets focused
7735 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7737 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007738 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7740 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007741 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7742
7743 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007744 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007745
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7747 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007748 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7750 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007751 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7752
7753 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007754 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007755 mWindow->consumeFocusEvent(false);
7756
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007757 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7758 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007759 mWindow->assertNoEvents();
7760}
7761
7762// Focus request can be pending until one window becomes visible.
7763TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7764 // Request focus on an invisible mirror.
7765 mWindow->setVisible(false);
7766 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007767 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007768 setFocusedWindow(mMirror);
7769
7770 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007772 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7773 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007774
7775 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007776 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007777
7778 // window gets focused
7779 mWindow->consumeFocusEvent(true);
7780 // window gets the pending key event
7781 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7782}
Prabir Pradhan99987712020-11-10 18:43:05 -08007783
7784class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7785protected:
7786 std::shared_ptr<FakeApplicationHandle> mApp;
7787 sp<FakeWindowHandle> mWindow;
7788 sp<FakeWindowHandle> mSecondWindow;
7789
7790 void SetUp() override {
7791 InputDispatcherTest::SetUp();
7792 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007793 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007794 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007795 mSecondWindow =
7796 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007797 mSecondWindow->setFocusable(true);
7798
7799 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007800 mDispatcher->onWindowInfosChanged(
7801 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08007802
7803 setFocusedWindow(mWindow);
7804 mWindow->consumeFocusEvent(true);
7805 }
7806
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007807 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007808 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007809 }
7810
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007811 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7812 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007813 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007814 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7815 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007816 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007817 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007818 }
7819};
7820
7821TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7822 // Ensure that capture cannot be obtained for unfocused windows.
7823 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7824 mFakePolicy->assertSetPointerCaptureNotCalled();
7825 mSecondWindow->assertNoEvents();
7826
7827 // Ensure that capture can be enabled from the focus window.
7828 requestAndVerifyPointerCapture(mWindow, true);
7829
7830 // Ensure that capture cannot be disabled from a window that does not have capture.
7831 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7832 mFakePolicy->assertSetPointerCaptureNotCalled();
7833
7834 // Ensure that capture can be disabled from the window with capture.
7835 requestAndVerifyPointerCapture(mWindow, false);
7836}
7837
7838TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007839 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007840
7841 setFocusedWindow(mSecondWindow);
7842
7843 // Ensure that the capture disabled event was sent first.
7844 mWindow->consumeCaptureEvent(false);
7845 mWindow->consumeFocusEvent(false);
7846 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007847 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007848
7849 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007850 notifyPointerCaptureChanged({});
7851 notifyPointerCaptureChanged(request);
7852 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007853 mWindow->assertNoEvents();
7854 mSecondWindow->assertNoEvents();
7855 mFakePolicy->assertSetPointerCaptureNotCalled();
7856}
7857
7858TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007859 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007860
7861 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007862 notifyPointerCaptureChanged({});
7863 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007864
7865 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007866 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007867 mWindow->consumeCaptureEvent(false);
7868 mWindow->assertNoEvents();
7869}
7870
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007871TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7872 requestAndVerifyPointerCapture(mWindow, true);
7873
7874 // The first window loses focus.
7875 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007876 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007877 mWindow->consumeCaptureEvent(false);
7878
7879 // Request Pointer Capture from the second window before the notification from InputReader
7880 // arrives.
7881 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007882 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007883
7884 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007885 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007886
7887 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007888 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007889
7890 mSecondWindow->consumeFocusEvent(true);
7891 mSecondWindow->consumeCaptureEvent(true);
7892}
7893
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007894TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7895 // App repeatedly enables and disables capture.
7896 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7897 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7898 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7899 mFakePolicy->assertSetPointerCaptureCalled(false);
7900 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7901 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7902
7903 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7904 // first request is now stale, this should do nothing.
7905 notifyPointerCaptureChanged(firstRequest);
7906 mWindow->assertNoEvents();
7907
7908 // InputReader notifies that the second request was enabled.
7909 notifyPointerCaptureChanged(secondRequest);
7910 mWindow->consumeCaptureEvent(true);
7911}
7912
Prabir Pradhan7092e262022-05-03 16:51:09 +00007913TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7914 requestAndVerifyPointerCapture(mWindow, true);
7915
7916 // App toggles pointer capture off and on.
7917 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7918 mFakePolicy->assertSetPointerCaptureCalled(false);
7919
7920 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7921 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7922
7923 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7924 // preceding "disable" request.
7925 notifyPointerCaptureChanged(enableRequest);
7926
7927 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7928 // any notifications.
7929 mWindow->assertNoEvents();
7930}
7931
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007932class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7933protected:
7934 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007935
7936 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7937 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7938
7939 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7940 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7941
7942 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7943 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7944 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7945 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7946 MAXIMUM_OBSCURING_OPACITY);
7947
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007948 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7949 static constexpr gui::Uid APP_B_UID{10002};
7950 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007951
7952 sp<FakeWindowHandle> mTouchWindow;
7953
7954 virtual void SetUp() override {
7955 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007956 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007957 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7958 }
7959
7960 virtual void TearDown() override {
7961 InputDispatcherTest::TearDown();
7962 mTouchWindow.clear();
7963 }
7964
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007965 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007966 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007967 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007968 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007969 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007970 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007971 return window;
7972 }
7973
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007974 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007975 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7976 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007977 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007978 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007979 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007980 return window;
7981 }
7982
7983 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007984 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7985 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7986 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007987 }
7988};
7989
7990TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007991 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007992 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007993 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007994
7995 touch();
7996
7997 mTouchWindow->assertNoEvents();
7998}
7999
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008000TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008001 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8002 const sp<FakeWindowHandle>& w =
8003 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008004 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008005
8006 touch();
8007
8008 mTouchWindow->assertNoEvents();
8009}
8010
8011TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008012 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8013 const sp<FakeWindowHandle>& w =
8014 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008015 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008016
8017 touch();
8018
8019 w->assertNoEvents();
8020}
8021
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008022TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008023 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008024 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008025
8026 touch();
8027
8028 mTouchWindow->consumeAnyMotionDown();
8029}
8030
8031TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008032 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008033 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008034 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008035 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008036
8037 touch({PointF{100, 100}});
8038
8039 mTouchWindow->consumeAnyMotionDown();
8040}
8041
8042TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008043 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008044 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008045 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008046
8047 touch();
8048
8049 mTouchWindow->consumeAnyMotionDown();
8050}
8051
8052TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8053 const sp<FakeWindowHandle>& w =
8054 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008055 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008056
8057 touch();
8058
8059 mTouchWindow->consumeAnyMotionDown();
8060}
8061
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008062TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8063 const sp<FakeWindowHandle>& w =
8064 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008065 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008066
8067 touch();
8068
8069 w->assertNoEvents();
8070}
8071
8072/**
8073 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8074 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8075 * window, the occluding window will still receive ACTION_OUTSIDE event.
8076 */
8077TEST_F(InputDispatcherUntrustedTouchesTest,
8078 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8079 const sp<FakeWindowHandle>& w =
8080 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008081 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008082 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008083
8084 touch();
8085
8086 w->consumeMotionOutside();
8087}
8088
8089TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8090 const sp<FakeWindowHandle>& w =
8091 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008092 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008093 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008094
8095 touch();
8096
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008097 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008098}
8099
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008100TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008101 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008102 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8103 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008104 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008105
8106 touch();
8107
8108 mTouchWindow->consumeAnyMotionDown();
8109}
8110
8111TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8112 const sp<FakeWindowHandle>& w =
8113 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8114 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008115 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008116
8117 touch();
8118
8119 mTouchWindow->consumeAnyMotionDown();
8120}
8121
8122TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008123 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008124 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8125 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008126 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008127
8128 touch();
8129
8130 mTouchWindow->assertNoEvents();
8131}
8132
8133TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8134 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8135 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008136 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8137 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008138 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008139 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8140 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008141 mDispatcher->onWindowInfosChanged(
8142 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008143
8144 touch();
8145
8146 mTouchWindow->assertNoEvents();
8147}
8148
8149TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8150 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8151 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008152 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8153 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008154 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008155 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8156 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008157 mDispatcher->onWindowInfosChanged(
8158 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008159
8160 touch();
8161
8162 mTouchWindow->consumeAnyMotionDown();
8163}
8164
8165TEST_F(InputDispatcherUntrustedTouchesTest,
8166 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8167 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008168 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8169 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008170 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008171 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8172 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008173 mDispatcher->onWindowInfosChanged(
8174 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008175
8176 touch();
8177
8178 mTouchWindow->consumeAnyMotionDown();
8179}
8180
8181TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8182 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008183 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8184 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008185 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008186 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8187 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008188 mDispatcher->onWindowInfosChanged(
8189 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008190
8191 touch();
8192
8193 mTouchWindow->assertNoEvents();
8194}
8195
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008196TEST_F(InputDispatcherUntrustedTouchesTest,
8197 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8198 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008199 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8200 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008201 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008202 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8203 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008204 mDispatcher->onWindowInfosChanged(
8205 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008206
8207 touch();
8208
8209 mTouchWindow->assertNoEvents();
8210}
8211
8212TEST_F(InputDispatcherUntrustedTouchesTest,
8213 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8214 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008215 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8216 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008217 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008218 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8219 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008220 mDispatcher->onWindowInfosChanged(
8221 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008222
8223 touch();
8224
8225 mTouchWindow->consumeAnyMotionDown();
8226}
8227
8228TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8229 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008230 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8231 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008232 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008233
8234 touch();
8235
8236 mTouchWindow->consumeAnyMotionDown();
8237}
8238
8239TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8240 const sp<FakeWindowHandle>& w =
8241 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008242 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008243
8244 touch();
8245
8246 mTouchWindow->consumeAnyMotionDown();
8247}
8248
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008249TEST_F(InputDispatcherUntrustedTouchesTest,
8250 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8251 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8252 const sp<FakeWindowHandle>& w =
8253 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008254 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008255
8256 touch();
8257
8258 mTouchWindow->assertNoEvents();
8259}
8260
8261TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8262 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8263 const sp<FakeWindowHandle>& w =
8264 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008265 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008266
8267 touch();
8268
8269 mTouchWindow->consumeAnyMotionDown();
8270}
8271
8272TEST_F(InputDispatcherUntrustedTouchesTest,
8273 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8274 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8275 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008276 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8277 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008278 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008279
8280 touch();
8281
8282 mTouchWindow->consumeAnyMotionDown();
8283}
8284
8285TEST_F(InputDispatcherUntrustedTouchesTest,
8286 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8287 const sp<FakeWindowHandle>& w1 =
8288 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8289 OPACITY_BELOW_THRESHOLD);
8290 const sp<FakeWindowHandle>& w2 =
8291 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8292 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008293 mDispatcher->onWindowInfosChanged(
8294 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008295
8296 touch();
8297
8298 mTouchWindow->assertNoEvents();
8299}
8300
8301/**
8302 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8303 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8304 * (which alone would result in allowing touches) does not affect the blocking behavior.
8305 */
8306TEST_F(InputDispatcherUntrustedTouchesTest,
8307 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8308 const sp<FakeWindowHandle>& wB =
8309 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8310 OPACITY_BELOW_THRESHOLD);
8311 const sp<FakeWindowHandle>& wC =
8312 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8313 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008314 mDispatcher->onWindowInfosChanged(
8315 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008316
8317 touch();
8318
8319 mTouchWindow->assertNoEvents();
8320}
8321
8322/**
8323 * This test is testing that a window from a different UID but with same application token doesn't
8324 * block the touch. Apps can share the application token for close UI collaboration for example.
8325 */
8326TEST_F(InputDispatcherUntrustedTouchesTest,
8327 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8328 const sp<FakeWindowHandle>& w =
8329 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8330 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008331 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008332
8333 touch();
8334
8335 mTouchWindow->consumeAnyMotionDown();
8336}
8337
arthurhungb89ccb02020-12-30 16:19:01 +08008338class InputDispatcherDragTests : public InputDispatcherTest {
8339protected:
8340 std::shared_ptr<FakeApplicationHandle> mApp;
8341 sp<FakeWindowHandle> mWindow;
8342 sp<FakeWindowHandle> mSecondWindow;
8343 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008344 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008345 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8346 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008347
8348 void SetUp() override {
8349 InputDispatcherTest::SetUp();
8350 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008351 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008352 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008353
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008354 mSecondWindow =
8355 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008356 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008357
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008358 mSpyWindow =
8359 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008360 mSpyWindow->setSpy(true);
8361 mSpyWindow->setTrustedOverlay(true);
8362 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8363
arthurhungb89ccb02020-12-30 16:19:01 +08008364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008365 mDispatcher->onWindowInfosChanged(
8366 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8367 {},
8368 0,
8369 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008370 }
8371
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008372 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8373 switch (fromSource) {
8374 case AINPUT_SOURCE_TOUCHSCREEN:
8375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8376 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8377 ADISPLAY_ID_DEFAULT, {50, 50}))
8378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8379 break;
8380 case AINPUT_SOURCE_STYLUS:
8381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8382 injectMotionEvent(
8383 mDispatcher,
8384 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8385 AINPUT_SOURCE_STYLUS)
8386 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008387 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008388 .x(50)
8389 .y(50))
8390 .build()));
8391 break;
8392 case AINPUT_SOURCE_MOUSE:
8393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8394 injectMotionEvent(
8395 mDispatcher,
8396 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8397 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8398 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008399 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008400 .x(50)
8401 .y(50))
8402 .build()));
8403 break;
8404 default:
8405 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8406 }
arthurhungb89ccb02020-12-30 16:19:01 +08008407
8408 // Window should receive motion event.
8409 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008410 // Spy window should also receive motion event
8411 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008412 }
8413
8414 // Start performing drag, we will create a drag window and transfer touch to it.
8415 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8416 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008417 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008418 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008419 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008420 }
arthurhungb89ccb02020-12-30 16:19:01 +08008421
8422 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008423 mDragWindow =
8424 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008425 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008426 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8427 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8428 {},
8429 0,
8430 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008431
8432 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008433 bool transferred =
8434 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008435 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008436 if (transferred) {
8437 mWindow->consumeMotionCancel();
8438 mDragWindow->consumeMotionDown();
8439 }
8440 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008441 }
8442};
8443
8444TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008445 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008446
8447 // Move on window.
8448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8449 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8450 ADISPLAY_ID_DEFAULT, {50, 50}))
8451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8452 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8453 mWindow->consumeDragEvent(false, 50, 50);
8454 mSecondWindow->assertNoEvents();
8455
8456 // Move to another window.
8457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8458 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8459 ADISPLAY_ID_DEFAULT, {150, 50}))
8460 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8461 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8462 mWindow->consumeDragEvent(true, 150, 50);
8463 mSecondWindow->consumeDragEvent(false, 50, 50);
8464
8465 // Move back to original window.
8466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8467 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8468 ADISPLAY_ID_DEFAULT, {50, 50}))
8469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8470 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8471 mWindow->consumeDragEvent(false, 50, 50);
8472 mSecondWindow->consumeDragEvent(true, -50, 50);
8473
8474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8475 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8477 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8478 mWindow->assertNoEvents();
8479 mSecondWindow->assertNoEvents();
8480}
8481
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008482TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008483 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008484
8485 // No cancel event after drag start
8486 mSpyWindow->assertNoEvents();
8487
8488 const MotionEvent secondFingerDownEvent =
8489 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8490 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008491 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8492 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008493 .build();
8494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8495 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8496 InputEventInjectionSync::WAIT_FOR_RESULT))
8497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8498
8499 // Receives cancel for first pointer after next pointer down
8500 mSpyWindow->consumeMotionCancel();
8501 mSpyWindow->consumeMotionDown();
8502
8503 mSpyWindow->assertNoEvents();
8504}
8505
arthurhungf452d0b2021-01-06 00:19:52 +08008506TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008507 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008508
8509 // Move on window.
8510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8511 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8512 ADISPLAY_ID_DEFAULT, {50, 50}))
8513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8514 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8515 mWindow->consumeDragEvent(false, 50, 50);
8516 mSecondWindow->assertNoEvents();
8517
8518 // Move to another window.
8519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8520 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8521 ADISPLAY_ID_DEFAULT, {150, 50}))
8522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8523 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8524 mWindow->consumeDragEvent(true, 150, 50);
8525 mSecondWindow->consumeDragEvent(false, 50, 50);
8526
8527 // drop to another window.
8528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8529 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8530 {150, 50}))
8531 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8532 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008533 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008534 mWindow->assertNoEvents();
8535 mSecondWindow->assertNoEvents();
8536}
8537
arthurhung6d4bed92021-03-17 11:59:33 +08008538TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008539 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008540
8541 // Move on window and keep button pressed.
8542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8543 injectMotionEvent(mDispatcher,
8544 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8545 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008546 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008547 .build()))
8548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8549 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8550 mWindow->consumeDragEvent(false, 50, 50);
8551 mSecondWindow->assertNoEvents();
8552
8553 // Move to another window and release button, expect to drop item.
8554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8555 injectMotionEvent(mDispatcher,
8556 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8557 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008559 .build()))
8560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8561 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8562 mWindow->assertNoEvents();
8563 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008564 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008565
8566 // nothing to the window.
8567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8568 injectMotionEvent(mDispatcher,
8569 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8570 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008572 .build()))
8573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8574 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8575 mWindow->assertNoEvents();
8576 mSecondWindow->assertNoEvents();
8577}
8578
Arthur Hung54745652022-04-20 07:17:41 +00008579TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008580 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008581
8582 // Set second window invisible.
8583 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008584 mDispatcher->onWindowInfosChanged(
8585 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08008586
8587 // Move on window.
8588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8589 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8590 ADISPLAY_ID_DEFAULT, {50, 50}))
8591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8592 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8593 mWindow->consumeDragEvent(false, 50, 50);
8594 mSecondWindow->assertNoEvents();
8595
8596 // Move to another window.
8597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8598 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8599 ADISPLAY_ID_DEFAULT, {150, 50}))
8600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8601 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8602 mWindow->consumeDragEvent(true, 150, 50);
8603 mSecondWindow->assertNoEvents();
8604
8605 // drop to another window.
8606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8607 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8608 {150, 50}))
8609 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8610 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008611 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008612 mWindow->assertNoEvents();
8613 mSecondWindow->assertNoEvents();
8614}
8615
Arthur Hung54745652022-04-20 07:17:41 +00008616TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008617 // Ensure window could track pointerIds if it didn't support split touch.
8618 mWindow->setPreventSplitting(true);
8619
Arthur Hung54745652022-04-20 07:17:41 +00008620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8621 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8622 {50, 50}))
8623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8624 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8625
8626 const MotionEvent secondFingerDownEvent =
8627 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8628 .displayId(ADISPLAY_ID_DEFAULT)
8629 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008630 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8631 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008632 .build();
8633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8634 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8635 InputEventInjectionSync::WAIT_FOR_RESULT))
8636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008637 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008638
8639 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008640 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008641}
8642
8643TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8644 // First down on second window.
8645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8646 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8647 {150, 50}))
8648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8649
8650 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8651
8652 // Second down on first window.
8653 const MotionEvent secondFingerDownEvent =
8654 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8655 .displayId(ADISPLAY_ID_DEFAULT)
8656 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008657 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8658 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008659 .build();
8660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8661 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8662 InputEventInjectionSync::WAIT_FOR_RESULT))
8663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8664 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8665
8666 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008667 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008668
8669 // Move on window.
8670 const MotionEvent secondFingerMoveEvent =
8671 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8672 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008673 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8674 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008675 .build();
8676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8677 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8678 InputEventInjectionSync::WAIT_FOR_RESULT));
8679 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8680 mWindow->consumeDragEvent(false, 50, 50);
8681 mSecondWindow->consumeMotionMove();
8682
8683 // Release the drag pointer should perform drop.
8684 const MotionEvent secondFingerUpEvent =
8685 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8686 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008687 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8688 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008689 .build();
8690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8691 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8692 InputEventInjectionSync::WAIT_FOR_RESULT));
8693 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008694 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008695 mWindow->assertNoEvents();
8696 mSecondWindow->consumeMotionMove();
8697}
8698
Arthur Hung3915c1f2022-05-31 07:17:17 +00008699TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008700 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008701
8702 // Update window of second display.
8703 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008704 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008705 mDispatcher->onWindowInfosChanged(
8706 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8707 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8708 {},
8709 0,
8710 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008711
8712 // Let second display has a touch state.
8713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8714 injectMotionEvent(mDispatcher,
8715 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8716 AINPUT_SOURCE_TOUCHSCREEN)
8717 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008718 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008719 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008720 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008721 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008722 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008723 mDispatcher->onWindowInfosChanged(
8724 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8725 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8726 {},
8727 0,
8728 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008729
8730 // Move on window.
8731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8732 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8733 ADISPLAY_ID_DEFAULT, {50, 50}))
8734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8735 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8736 mWindow->consumeDragEvent(false, 50, 50);
8737 mSecondWindow->assertNoEvents();
8738
8739 // Move to another window.
8740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8741 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8742 ADISPLAY_ID_DEFAULT, {150, 50}))
8743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8744 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8745 mWindow->consumeDragEvent(true, 150, 50);
8746 mSecondWindow->consumeDragEvent(false, 50, 50);
8747
8748 // drop to another window.
8749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8750 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8751 {150, 50}))
8752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8753 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008754 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008755 mWindow->assertNoEvents();
8756 mSecondWindow->assertNoEvents();
8757}
8758
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008759TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8760 startDrag(true, AINPUT_SOURCE_MOUSE);
8761 // Move on window.
8762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8763 injectMotionEvent(mDispatcher,
8764 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8765 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8766 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008767 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008768 .x(50)
8769 .y(50))
8770 .build()))
8771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8772 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8773 mWindow->consumeDragEvent(false, 50, 50);
8774 mSecondWindow->assertNoEvents();
8775
8776 // Move to another window.
8777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8778 injectMotionEvent(mDispatcher,
8779 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8780 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8781 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008782 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008783 .x(150)
8784 .y(50))
8785 .build()))
8786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8787 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8788 mWindow->consumeDragEvent(true, 150, 50);
8789 mSecondWindow->consumeDragEvent(false, 50, 50);
8790
8791 // drop to another window.
8792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8793 injectMotionEvent(mDispatcher,
8794 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8795 .buttonState(0)
8796 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008797 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008798 .x(150)
8799 .y(50))
8800 .build()))
8801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8802 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008803 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008804 mWindow->assertNoEvents();
8805 mSecondWindow->assertNoEvents();
8806}
8807
Vishnu Nair062a8672021-09-03 16:07:44 -07008808class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8809
8810TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008812 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8813 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008814 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8816 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008817 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008818 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008819 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008820
8821 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008822 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008823 window->assertNoEvents();
8824
Prabir Pradhan678438e2023-04-13 19:32:51 +00008825 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8826 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008827 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8828 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008829 window->assertNoEvents();
8830
8831 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008832 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008833 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008834
Prabir Pradhan678438e2023-04-13 19:32:51 +00008835 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008836 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8837
Prabir Pradhan678438e2023-04-13 19:32:51 +00008838 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8839 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008840 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8841 window->assertNoEvents();
8842}
8843
8844TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8845 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8846 std::make_shared<FakeApplicationHandle>();
8847 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008848 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8849 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008850 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008851 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008852 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008854 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8855 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008856 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008857 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008858 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8859 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008860 mDispatcher->onWindowInfosChanged(
8861 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008862 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008863 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008864
8865 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008866 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008867 window->assertNoEvents();
8868
Prabir Pradhan678438e2023-04-13 19:32:51 +00008869 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8870 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008871 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8872 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008873 window->assertNoEvents();
8874
8875 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008876 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008877 mDispatcher->onWindowInfosChanged(
8878 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008879
Prabir Pradhan678438e2023-04-13 19:32:51 +00008880 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008881 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8882
Prabir Pradhan678438e2023-04-13 19:32:51 +00008883 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8884 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008885 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8886 window->assertNoEvents();
8887}
8888
8889TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8890 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8891 std::make_shared<FakeApplicationHandle>();
8892 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008893 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8894 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008895 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008896 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008897 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008899 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8900 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008901 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008902 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008903 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8904 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008905 mDispatcher->onWindowInfosChanged(
8906 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008907 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008908 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008909
8910 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008911 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008912 window->assertNoEvents();
8913
Prabir Pradhan678438e2023-04-13 19:32:51 +00008914 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8915 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008916 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8917 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008918 window->assertNoEvents();
8919
8920 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008921 mDispatcher->onWindowInfosChanged(
8922 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008923
Prabir Pradhan678438e2023-04-13 19:32:51 +00008924 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008925 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8926
Prabir Pradhan678438e2023-04-13 19:32:51 +00008927 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8928 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008929 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8930 window->assertNoEvents();
8931}
8932
Antonio Kantekf16f2832021-09-28 04:39:20 +00008933class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8934protected:
8935 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008936 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008937 sp<FakeWindowHandle> mWindow;
8938 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008939 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008940
8941 void SetUp() override {
8942 InputDispatcherTest::SetUp();
8943
8944 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008945 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008946 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008947 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008948 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008949 mSecondWindow =
8950 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008951 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008952 mThirdWindow =
8953 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8954 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8955 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008956
8957 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008958 mDispatcher->onWindowInfosChanged(
8959 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
8960 {},
8961 0,
8962 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00008963 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008964 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008965
Antonio Kantek15beb512022-06-13 22:35:41 +00008966 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008967 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008968 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008969 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8970 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008971 mThirdWindow->assertNoEvents();
8972 }
8973
8974 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8975 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008976 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008977 SECOND_DISPLAY_ID)) {
8978 mWindow->assertNoEvents();
8979 mSecondWindow->assertNoEvents();
8980 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008981 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008982 }
8983
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008984 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008985 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008986 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8987 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008988 mWindow->consumeTouchModeEvent(inTouchMode);
8989 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008990 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008991 }
8992};
8993
Antonio Kantek26defcf2022-02-08 01:12:27 +00008994TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008995 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008996 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8997 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008998 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008999}
9000
Antonio Kantek26defcf2022-02-08 01:12:27 +00009001TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9002 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009003 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009004 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009005 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009006 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009007 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009008 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009009 mWindow->assertNoEvents();
9010 mSecondWindow->assertNoEvents();
9011}
9012
9013TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9014 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009015 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009016 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009017 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009018 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009019 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009020}
9021
Antonio Kantekf16f2832021-09-28 04:39:20 +00009022TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009023 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009024 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9025 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009026 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009027 mWindow->assertNoEvents();
9028 mSecondWindow->assertNoEvents();
9029}
9030
Antonio Kantek15beb512022-06-13 22:35:41 +00009031TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9032 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9033 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9034 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009035 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009036 mWindow->assertNoEvents();
9037 mSecondWindow->assertNoEvents();
9038 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9039}
9040
Antonio Kantek48710e42022-03-24 14:19:30 -07009041TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9042 // Interact with the window first.
9043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
9044 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9045 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9046
9047 // Then remove focus.
9048 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009049 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009050
9051 // Assert that caller can switch touch mode by owning one of the last interacted window.
9052 const WindowInfo& windowInfo = *mWindow->getInfo();
9053 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9054 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009055 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009056}
9057
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009058class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9059public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009060 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009061 std::shared_ptr<FakeApplicationHandle> application =
9062 std::make_shared<FakeApplicationHandle>();
9063 std::string name = "Fake Spy ";
9064 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009065 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9066 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009067 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009068 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009069 return spy;
9070 }
9071
9072 sp<FakeWindowHandle> createForeground() {
9073 std::shared_ptr<FakeApplicationHandle> application =
9074 std::make_shared<FakeApplicationHandle>();
9075 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009076 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9077 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009078 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009079 return window;
9080 }
9081
9082private:
9083 int mSpyCount{0};
9084};
9085
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009086using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009087/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009088 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9089 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009090TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009091 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009092 ScopedSilentDeath _silentDeath;
9093
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009094 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009095 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009096 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009097 ".* not a trusted overlay");
9098}
9099
9100/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009101 * Input injection into a display with a spy window but no foreground windows should succeed.
9102 */
9103TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009104 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009105 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009106
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9108 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9110 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9111}
9112
9113/**
9114 * Verify the order in which different input windows receive events. The touched foreground window
9115 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9116 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9117 * receive events before ones belows it.
9118 *
9119 * Here, we set up a scenario with four windows in the following Z order from the top:
9120 * spy1, spy2, window, spy3.
9121 * We then inject an event and verify that the foreground "window" receives it first, followed by
9122 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9123 * window.
9124 */
9125TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9126 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009127 auto spy1 = createSpy();
9128 auto spy2 = createSpy();
9129 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009130 mDispatcher->onWindowInfosChanged(
9131 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009132 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9133 const size_t numChannels = channels.size();
9134
Michael Wright8e9a8562022-02-09 13:44:29 +00009135 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009136 if (!epollFd.ok()) {
9137 FAIL() << "Failed to create epoll fd";
9138 }
9139
9140 for (size_t i = 0; i < numChannels; i++) {
9141 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9142 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9143 FAIL() << "Failed to add fd to epoll";
9144 }
9145 }
9146
9147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9148 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9149 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9150
9151 std::vector<size_t> eventOrder;
9152 std::vector<struct epoll_event> events(numChannels);
9153 for (;;) {
9154 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9155 (100ms).count());
9156 if (nFds < 0) {
9157 FAIL() << "Failed to call epoll_wait";
9158 }
9159 if (nFds == 0) {
9160 break; // epoll_wait timed out
9161 }
9162 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009163 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009164 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009165 channels[i]->consumeMotionDown();
9166 }
9167 }
9168
9169 // Verify the order in which the events were received.
9170 EXPECT_EQ(3u, eventOrder.size());
9171 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9172 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9173 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9174}
9175
9176/**
9177 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9178 */
9179TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9180 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009181 auto spy = createSpy();
9182 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009183 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009184
9185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9186 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9188 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9189 spy->assertNoEvents();
9190}
9191
9192/**
9193 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9194 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9195 * to the window.
9196 */
9197TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9198 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009199 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009200 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009201 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009202
9203 // Inject an event outside the spy window's touchable region.
9204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9205 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9206 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9207 window->consumeMotionDown();
9208 spy->assertNoEvents();
9209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9210 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9212 window->consumeMotionUp();
9213 spy->assertNoEvents();
9214
9215 // Inject an event inside the spy window's touchable region.
9216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9217 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9218 {5, 10}))
9219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9220 window->consumeMotionDown();
9221 spy->consumeMotionDown();
9222}
9223
9224/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009225 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009226 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009227 */
9228TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9229 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009230 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009231 auto spy = createSpy();
9232 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009233 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009234 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009235 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009236
9237 // Inject an event outside the spy window's frame and touchable region.
9238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009239 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9240 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9242 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009243 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009244}
9245
9246/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009247 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9248 * pointers that are down within its bounds.
9249 */
9250TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9251 auto windowLeft = createForeground();
9252 windowLeft->setFrame({0, 0, 100, 200});
9253 auto windowRight = createForeground();
9254 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009255 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009256 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009257 mDispatcher->onWindowInfosChanged(
9258 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009259
9260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9261 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9262 {50, 50}))
9263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9264 windowLeft->consumeMotionDown();
9265 spy->consumeMotionDown();
9266
9267 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009268 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009269 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009270 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9271 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009272 .build();
9273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9274 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9275 InputEventInjectionSync::WAIT_FOR_RESULT))
9276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9277 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009278 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009279}
9280
9281/**
9282 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9283 * the spy should receive the second pointer with ACTION_DOWN.
9284 */
9285TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9286 auto window = createForeground();
9287 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009288 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009289 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009290 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009291
9292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9293 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9294 {50, 50}))
9295 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9296 window->consumeMotionDown();
9297 spyRight->assertNoEvents();
9298
9299 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009300 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009301 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009302 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9303 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009304 .build();
9305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9306 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9307 InputEventInjectionSync::WAIT_FOR_RESULT))
9308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009309 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009310 spyRight->consumeMotionDown();
9311}
9312
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009313/**
9314 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9315 * windows should be allowed to control split touch.
9316 */
9317TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009318 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009319 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009320 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009321 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009322
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009323 auto window = createForeground();
9324 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009325
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009326 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009327
9328 // First finger down, no window touched.
9329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9330 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9331 {100, 200}))
9332 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9333 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9334 window->assertNoEvents();
9335
9336 // Second finger down on window, the window should receive touch down.
9337 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009338 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009339 .displayId(ADISPLAY_ID_DEFAULT)
9340 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009341 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9342 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009343 .build();
9344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9345 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9346 InputEventInjectionSync::WAIT_FOR_RESULT))
9347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9348
9349 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009350 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009351}
9352
9353/**
9354 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9355 * do not receive key events.
9356 */
9357TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009358 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009359 spy->setFocusable(false);
9360
9361 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009362 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009363 setFocusedWindow(window);
9364 window->consumeFocusEvent(true);
9365
9366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9367 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9368 window->consumeKeyDown(ADISPLAY_ID_NONE);
9369
9370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9371 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9372 window->consumeKeyUp(ADISPLAY_ID_NONE);
9373
9374 spy->assertNoEvents();
9375}
9376
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009377using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9378
9379/**
9380 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9381 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9382 */
9383TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9384 auto window = createForeground();
9385 auto spy1 = createSpy();
9386 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009387 mDispatcher->onWindowInfosChanged(
9388 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009389
9390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9391 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9392 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9393 window->consumeMotionDown();
9394 spy1->consumeMotionDown();
9395 spy2->consumeMotionDown();
9396
9397 // Pilfer pointers from the second spy window.
9398 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9399 spy2->assertNoEvents();
9400 spy1->consumeMotionCancel();
9401 window->consumeMotionCancel();
9402
9403 // The rest of the gesture should only be sent to the second spy window.
9404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9405 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9406 ADISPLAY_ID_DEFAULT))
9407 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9408 spy2->consumeMotionMove();
9409 spy1->assertNoEvents();
9410 window->assertNoEvents();
9411}
9412
9413/**
9414 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9415 * in the middle of the gesture.
9416 */
9417TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9418 auto window = createForeground();
9419 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009420 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009421
9422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9423 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9425 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9426 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9427
9428 window->releaseChannel();
9429
9430 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9431
9432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9433 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9435 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9436}
9437
9438/**
9439 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9440 * the spy, but not to any other windows.
9441 */
9442TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9443 auto spy = createSpy();
9444 auto window = createForeground();
9445
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009446 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009447
9448 // First finger down on the window and the spy.
9449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9450 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9451 {100, 200}))
9452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9453 spy->consumeMotionDown();
9454 window->consumeMotionDown();
9455
9456 // Spy window pilfers the pointers.
9457 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9458 window->consumeMotionCancel();
9459
9460 // Second finger down on the window and spy, but the window should not receive the pointer down.
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(100).y(200))
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
Harry Cutts33476232023-01-30 19:57:29 +00009473 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009474
9475 // Third finger goes down outside all windows, so injection should fail.
9476 const MotionEvent thirdFingerDownEvent =
9477 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9478 .displayId(ADISPLAY_ID_DEFAULT)
9479 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009480 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9481 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9482 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009483 .build();
9484 ASSERT_EQ(InputEventInjectionResult::FAILED,
9485 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9486 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009487 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009488
9489 spy->assertNoEvents();
9490 window->assertNoEvents();
9491}
9492
9493/**
9494 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9495 */
9496TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9497 auto spy = createSpy();
9498 spy->setFrame(Rect(0, 0, 100, 100));
9499 auto window = createForeground();
9500 window->setFrame(Rect(0, 0, 200, 200));
9501
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009502 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009503
9504 // First finger down on the window only
9505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9506 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9507 {150, 150}))
9508 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9509 window->consumeMotionDown();
9510
9511 // Second finger down on the spy and window
9512 const MotionEvent secondFingerDownEvent =
9513 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9514 .displayId(ADISPLAY_ID_DEFAULT)
9515 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009516 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9517 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009518 .build();
9519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9520 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9521 InputEventInjectionSync::WAIT_FOR_RESULT))
9522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9523 spy->consumeMotionDown();
9524 window->consumeMotionPointerDown(1);
9525
9526 // Third finger down on the spy and window
9527 const MotionEvent thirdFingerDownEvent =
9528 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9529 .displayId(ADISPLAY_ID_DEFAULT)
9530 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009531 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9532 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9533 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009534 .build();
9535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9536 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9537 InputEventInjectionSync::WAIT_FOR_RESULT))
9538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9539 spy->consumeMotionPointerDown(1);
9540 window->consumeMotionPointerDown(2);
9541
9542 // Spy window pilfers the pointers.
9543 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009544 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9545 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009546
9547 spy->assertNoEvents();
9548 window->assertNoEvents();
9549}
9550
9551/**
9552 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9553 * other windows should be canceled. If this results in the cancellation of all pointers for some
9554 * window, then that window should receive ACTION_CANCEL.
9555 */
9556TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9557 auto spy = createSpy();
9558 spy->setFrame(Rect(0, 0, 100, 100));
9559 auto window = createForeground();
9560 window->setFrame(Rect(0, 0, 200, 200));
9561
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009562 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009563
9564 // First finger down on both spy and window
9565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9566 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9567 {10, 10}))
9568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9569 window->consumeMotionDown();
9570 spy->consumeMotionDown();
9571
9572 // Second finger down on the spy and window
9573 const MotionEvent secondFingerDownEvent =
9574 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9575 .displayId(ADISPLAY_ID_DEFAULT)
9576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9578 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009579 .build();
9580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9581 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9582 InputEventInjectionSync::WAIT_FOR_RESULT))
9583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9584 spy->consumeMotionPointerDown(1);
9585 window->consumeMotionPointerDown(1);
9586
9587 // Spy window pilfers the pointers.
9588 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9589 window->consumeMotionCancel();
9590
9591 spy->assertNoEvents();
9592 window->assertNoEvents();
9593}
9594
9595/**
9596 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9597 * be sent to other windows
9598 */
9599TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9600 auto spy = createSpy();
9601 spy->setFrame(Rect(0, 0, 100, 100));
9602 auto window = createForeground();
9603 window->setFrame(Rect(0, 0, 200, 200));
9604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009605 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009606
9607 // First finger down on both window and spy
9608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9609 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9610 {10, 10}))
9611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9612 window->consumeMotionDown();
9613 spy->consumeMotionDown();
9614
9615 // Spy window pilfers the pointers.
9616 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9617 window->consumeMotionCancel();
9618
9619 // Second finger down on the window only
9620 const MotionEvent secondFingerDownEvent =
9621 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9622 .displayId(ADISPLAY_ID_DEFAULT)
9623 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009624 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9625 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009626 .build();
9627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9628 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9629 InputEventInjectionSync::WAIT_FOR_RESULT))
9630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9631 window->consumeMotionDown();
9632 window->assertNoEvents();
9633
9634 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9635 spy->consumeMotionMove();
9636 spy->assertNoEvents();
9637}
9638
Prabir Pradhand65552b2021-10-07 11:23:50 -07009639class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9640public:
9641 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9642 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9643 std::make_shared<FakeApplicationHandle>();
9644 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009645 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9646 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009647 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009648 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009649 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009650 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009651 overlay->setTrustedOverlay(true);
9652
9653 std::shared_ptr<FakeApplicationHandle> application =
9654 std::make_shared<FakeApplicationHandle>();
9655 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009656 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9657 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009658 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009659 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009660
9661 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009662 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009663 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009664 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009665 return {std::move(overlay), std::move(window)};
9666 }
9667
9668 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009669 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009670 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009671 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009672 }
9673
9674 void sendStylusEvent(int32_t action) {
9675 NotifyMotionArgs motionArgs =
9676 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9677 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009678 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009679 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009680 }
9681};
9682
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009683using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9684
9685TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009686 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009687 ScopedSilentDeath _silentDeath;
9688
Prabir Pradhand65552b2021-10-07 11:23:50 -07009689 auto [overlay, window] = setupStylusOverlayScenario();
9690 overlay->setTrustedOverlay(false);
9691 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009692 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
9693 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -07009694 ".* not a trusted overlay");
9695}
9696
9697TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9698 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009699 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009700
9701 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9702 overlay->consumeMotionDown();
9703 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9704 overlay->consumeMotionUp();
9705
9706 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9707 window->consumeMotionDown();
9708 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9709 window->consumeMotionUp();
9710
9711 overlay->assertNoEvents();
9712 window->assertNoEvents();
9713}
9714
9715TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9716 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009717 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009718 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009719
9720 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9721 overlay->consumeMotionDown();
9722 window->consumeMotionDown();
9723 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9724 overlay->consumeMotionUp();
9725 window->consumeMotionUp();
9726
9727 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9728 window->consumeMotionDown();
9729 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9730 window->consumeMotionUp();
9731
9732 overlay->assertNoEvents();
9733 window->assertNoEvents();
9734}
9735
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009736/**
9737 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9738 * The scenario is as follows:
9739 * - The stylus interceptor overlay is configured as a spy window.
9740 * - The stylus interceptor spy receives the start of a new stylus gesture.
9741 * - It pilfers pointers and then configures itself to no longer be a spy.
9742 * - The stylus interceptor continues to receive the rest of the gesture.
9743 */
9744TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9745 auto [overlay, window] = setupStylusOverlayScenario();
9746 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009747 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009748
9749 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9750 overlay->consumeMotionDown();
9751 window->consumeMotionDown();
9752
9753 // The interceptor pilfers the pointers.
9754 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9755 window->consumeMotionCancel();
9756
9757 // The interceptor configures itself so that it is no longer a spy.
9758 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009759 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009760
9761 // It continues to receive the rest of the stylus gesture.
9762 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9763 overlay->consumeMotionMove();
9764 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9765 overlay->consumeMotionUp();
9766
9767 window->assertNoEvents();
9768}
9769
Prabir Pradhan5735a322022-04-11 17:23:34 +00009770struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009771 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009772 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009773 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9774 std::unique_ptr<InputDispatcher>& mDispatcher;
9775
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009776 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009777 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9778
9779 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9780 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9781 ADISPLAY_ID_DEFAULT, {100, 200},
9782 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9783 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9784 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9785 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9786 }
9787
9788 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009789 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009790 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009791 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009792 mPolicyFlags);
9793 }
9794
9795 sp<FakeWindowHandle> createWindow() const {
9796 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9797 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009798 sp<FakeWindowHandle> window =
9799 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9800 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009801 window->setOwnerInfo(mPid, mUid);
9802 return window;
9803 }
9804};
9805
9806using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9807
9808TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009809 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009810 auto window = owner.createWindow();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009811 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009812
9813 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9814 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9815 window->consumeMotionDown();
9816
9817 setFocusedWindow(window);
9818 window->consumeFocusEvent(true);
9819
9820 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9821 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9822 window->consumeKeyDown(ADISPLAY_ID_NONE);
9823}
9824
9825TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009826 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009827 auto window = owner.createWindow();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009828 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009829
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009830 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009831 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9832 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9833
9834 setFocusedWindow(window);
9835 window->consumeFocusEvent(true);
9836
9837 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9838 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9839 window->assertNoEvents();
9840}
9841
9842TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009843 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009844 auto window = owner.createWindow();
9845 auto spy = owner.createWindow();
9846 spy->setSpy(true);
9847 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009848 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009849
9850 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9851 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9852 spy->consumeMotionDown();
9853 window->consumeMotionDown();
9854}
9855
9856TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009857 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009858 auto window = owner.createWindow();
9859
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009860 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009861 auto randosSpy = rando.createWindow();
9862 randosSpy->setSpy(true);
9863 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009864 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009865
9866 // The event is targeted at owner's window, so injection should succeed, but the spy should
9867 // not receive the event.
9868 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9869 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9870 randosSpy->assertNoEvents();
9871 window->consumeMotionDown();
9872}
9873
9874TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009875 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009876 auto window = owner.createWindow();
9877
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009878 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009879 auto randosSpy = rando.createWindow();
9880 randosSpy->setSpy(true);
9881 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009882 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009883
9884 // A user that has injection permission can inject into any window.
9885 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9886 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9887 ADISPLAY_ID_DEFAULT));
9888 randosSpy->consumeMotionDown();
9889 window->consumeMotionDown();
9890
9891 setFocusedWindow(randosSpy);
9892 randosSpy->consumeFocusEvent(true);
9893
9894 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9895 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9896 window->assertNoEvents();
9897}
9898
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009899TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009900 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009901 auto window = owner.createWindow();
9902
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009903 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009904 auto randosWindow = rando.createWindow();
9905 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9906 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009907 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009908
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009909 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009910 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9911 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9912 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009913 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009914}
9915
Garfield Tane84e6f92019-08-29 17:28:41 -07009916} // namespace android::inputdispatcher