blob: 609e4dd5b4a23ff959e9fa01569a2735279ce1ac [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
Arthur Hungb92218b2018-08-14 12:00:21 +0800864// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700865static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700866// Default input dispatching timeout if there is no focused application or paused window
867// from which to determine an appropriate dispatching timeout.
868static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
869 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
870 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800871
872class FakeApplicationHandle : public InputApplicationHandle {
873public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700874 FakeApplicationHandle() {
875 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700876 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500877 mInfo.dispatchingTimeoutMillis =
878 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700879 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 virtual ~FakeApplicationHandle() {}
881
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000882 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700883
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500884 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
885 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700886 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800887};
888
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800889class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800890public:
Garfield Tan15601662020-09-22 15:32:38 -0700891 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800892 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700893 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800894 }
895
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 InputEvent* event;
898 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
899 if (!consumeSeq) {
900 return nullptr;
901 }
902 finishEvent(*consumeSeq);
903 return event;
904 }
905
906 /**
907 * Receive an event without acknowledging it.
908 * Return the sequence number that could later be used to send finished signal.
909 */
910 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800911 uint32_t consumeSeq;
912 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800913
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800914 std::chrono::time_point start = std::chrono::steady_clock::now();
915 status_t status = WOULD_BLOCK;
916 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000917 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800918 &event);
919 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
920 if (elapsed > 100ms) {
921 break;
922 }
923 }
924
925 if (status == WOULD_BLOCK) {
926 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700927 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928 }
929
930 if (status != OK) {
931 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700932 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 }
934 if (event == nullptr) {
935 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700936 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 if (outEvent != nullptr) {
939 *outEvent = event;
940 }
941 return consumeSeq;
942 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 /**
945 * To be used together with "receiveEvent" to complete the consumption of an event.
946 */
947 void finishEvent(uint32_t consumeSeq) {
948 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
949 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800950 }
951
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000952 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
953 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
954 ASSERT_EQ(OK, status);
955 }
956
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700957 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000958 std::optional<int32_t> expectedDisplayId,
959 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800960 InputEvent* event = consume();
961
962 ASSERT_NE(nullptr, event) << mName.c_str()
963 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800964 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
966 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800967
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000968 if (expectedDisplayId.has_value()) {
969 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
970 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800971
Tiger Huang8664f8c2018-10-11 19:14:35 +0800972 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800974 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
975 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976 if (expectedFlags.has_value()) {
977 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
978 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979 break;
980 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800982 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000983 assertMotionAction(expectedAction, motionEvent.getAction());
984
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000985 if (expectedFlags.has_value()) {
986 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
987 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800988 break;
989 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700990 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100991 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
992 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700993 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800994 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000997 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
998 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700999 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001000 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1001 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001002 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001003 }
1004
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001005 MotionEvent* consumeMotion() {
1006 InputEvent* event = consume();
1007
1008 if (event == nullptr) {
1009 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1010 return nullptr;
1011 }
1012
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001013 if (event->getType() != InputEventType::MOTION) {
1014 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001015 return nullptr;
1016 }
1017 return static_cast<MotionEvent*>(event);
1018 }
1019
1020 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1021 MotionEvent* motionEvent = consumeMotion();
1022 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1023 ASSERT_THAT(*motionEvent, matcher);
1024 }
1025
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001026 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1027 InputEvent* event = consume();
1028 ASSERT_NE(nullptr, event) << mName.c_str()
1029 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001030 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1031 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001032
1033 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1034 << mName.c_str() << ": event displayId should always be NONE.";
1035
1036 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1037 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001038 }
1039
Prabir Pradhan99987712020-11-10 18:43:05 -08001040 void consumeCaptureEvent(bool hasCapture) {
1041 const InputEvent* event = consume();
1042 ASSERT_NE(nullptr, event) << mName.c_str()
1043 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001044 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1045 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001046
1047 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
1050 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1051 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1052 }
1053
arthurhungb89ccb02020-12-30 16:19:01 +08001054 void consumeDragEvent(bool isExiting, float x, float y) {
1055 const InputEvent* event = consume();
1056 ASSERT_NE(nullptr, event) << mName.c_str()
1057 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001059
1060 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1061 << mName.c_str() << ": event displayId should always be NONE.";
1062
1063 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1064 EXPECT_EQ(isExiting, dragEvent.isExiting());
1065 EXPECT_EQ(x, dragEvent.getX());
1066 EXPECT_EQ(y, dragEvent.getY());
1067 }
1068
Antonio Kantekf16f2832021-09-28 04:39:20 +00001069 void consumeTouchModeEvent(bool inTouchMode) {
1070 const InputEvent* event = consume();
1071 ASSERT_NE(nullptr, event) << mName.c_str()
1072 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1074 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001075
1076 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1077 << mName.c_str() << ": event displayId should always be NONE.";
1078 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1079 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1080 }
1081
chaviwd1c23182019-12-20 18:44:56 -08001082 void assertNoEvents() {
1083 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001084 if (event == nullptr) {
1085 return;
1086 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001087 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001088 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1089 ADD_FAILURE() << "Received key event "
1090 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001091 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001092 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1093 ADD_FAILURE() << "Received motion event "
1094 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001095 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001096 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1097 ADD_FAILURE() << "Received focus event, hasFocus = "
1098 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001099 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001100 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1101 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1102 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001103 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001104 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1105 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1106 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001107 }
1108 FAIL() << mName.c_str()
1109 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001110 }
1111
1112 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1113
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001114 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1115
chaviwd1c23182019-12-20 18:44:56 -08001116protected:
1117 std::unique_ptr<InputConsumer> mConsumer;
1118 PreallocatedInputEventFactory mEventFactory;
1119
1120 std::string mName;
1121};
1122
chaviw3277faf2021-05-19 16:45:23 -05001123class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001124public:
1125 static const int32_t WIDTH = 600;
1126 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001127
Chris Yea209fde2020-07-22 13:54:51 -07001128 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001129 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001130 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001131 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001132 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001133 base::Result<std::unique_ptr<InputChannel>> channel =
1134 dispatcher->createInputChannel(name);
1135 token = (*channel)->getConnectionToken();
1136 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001137 }
1138
1139 inputApplicationHandle->updateInfo();
1140 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1141
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001142 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001143 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001144 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001145 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001146 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001147 mInfo.frameLeft = 0;
1148 mInfo.frameTop = 0;
1149 mInfo.frameRight = WIDTH;
1150 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001151 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001152 mInfo.globalScaleFactor = 1.0;
1153 mInfo.touchableRegion.clear();
1154 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001155 mInfo.ownerPid = WINDOW_PID;
1156 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001157 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001158 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001159 }
1160
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001161 sp<FakeWindowHandle> clone(int32_t displayId) {
1162 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1163 handle->mInfo = mInfo;
1164 handle->mInfo.displayId = displayId;
1165 handle->mInfo.id = sId++;
1166 handle->mInputReceiver = mInputReceiver;
1167 return handle;
1168 }
1169
1170 /**
1171 * This is different from clone, because clone will make a "mirror" window - a window with the
1172 * same token, but a different ID. The original window and the clone window are allowed to be
1173 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1174 * This function will create a different object of WindowInfoHandle, but with the same
1175 * properties as the original object - including the ID.
1176 * You can use either the old or the new object to consume the events.
1177 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1178 * at the same time inside dispatcher.
1179 */
1180 sp<FakeWindowHandle> duplicate() {
1181 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1182 handle->mInfo = mInfo;
1183 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001184 return handle;
1185 }
1186
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001187 void setTouchable(bool touchable) {
1188 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1189 }
chaviwd1c23182019-12-20 18:44:56 -08001190
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001191 void setFocusable(bool focusable) {
1192 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1193 }
1194
1195 void setVisible(bool visible) {
1196 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1197 }
Vishnu Nair958da932020-08-21 17:12:37 -07001198
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001199 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001200 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001201 }
1202
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001203 void setPaused(bool paused) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1205 }
1206
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001207 void setPreventSplitting(bool preventSplitting) {
1208 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001209 }
1210
1211 void setSlippery(bool slippery) {
1212 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1213 }
1214
1215 void setWatchOutsideTouch(bool watchOutside) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1217 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001218
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001219 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1220
1221 void setInterceptsStylus(bool interceptsStylus) {
1222 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1223 }
1224
1225 void setDropInput(bool dropInput) {
1226 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1227 }
1228
1229 void setDropInputIfObscured(bool dropInputIfObscured) {
1230 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1231 }
1232
1233 void setNoInputChannel(bool noInputChannel) {
1234 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1235 }
1236
Josep del Riob3981622023-04-18 15:49:45 +00001237 void setDisableUserActivity(bool disableUserActivity) {
1238 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1239 }
1240
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001241 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1242
chaviw3277faf2021-05-19 16:45:23 -05001243 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001244
Bernardo Rufino7393d172021-02-26 13:56:11 +00001245 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1246
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001247 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001248 mInfo.frameLeft = frame.left;
1249 mInfo.frameTop = frame.top;
1250 mInfo.frameRight = frame.right;
1251 mInfo.frameBottom = frame.bottom;
1252 mInfo.touchableRegion.clear();
1253 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001254
1255 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1256 ui::Transform translate;
1257 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1258 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001259 }
1260
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001261 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1262
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001263 void setIsWallpaper(bool isWallpaper) {
1264 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1265 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001266
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001267 void setDupTouchToWallpaper(bool hasWallpaper) {
1268 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1269 }
chaviwd1c23182019-12-20 18:44:56 -08001270
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001271 void setTrustedOverlay(bool trustedOverlay) {
1272 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1273 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001274
chaviw9eaa22c2020-07-01 16:21:27 -07001275 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1276 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1277 }
1278
1279 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001280
yunho.shinf4a80b82020-11-16 21:13:57 +09001281 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1282
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001283 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001284 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001285 }
1286
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001287 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001288 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001289 }
1290
Svet Ganov5d3bc372020-01-26 23:11:07 -08001291 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001293 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1294 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001295 }
1296
1297 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001299 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1300 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001301 }
1302
1303 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001304 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001305 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1306 }
1307
1308 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1309 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001310 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001311 expectedFlags);
1312 }
1313
Svet Ganov5d3bc372020-01-26 23:11:07 -08001314 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001315 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1316 int32_t expectedFlags = 0) {
1317 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1318 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001319 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001320 }
1321
1322 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001323 int32_t expectedFlags = 0) {
1324 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1325 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001327 }
1328
1329 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001330 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001331 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001332 expectedFlags);
1333 }
1334
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001335 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1336 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001337 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001338 expectedFlags);
1339 }
1340
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001341 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1342 int32_t expectedFlags = 0) {
1343 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001344 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001345 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001346 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1347 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1348 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1349 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1350 }
1351
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001352 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1353 ASSERT_NE(mInputReceiver, nullptr)
1354 << "Cannot consume events from a window with no receiver";
1355 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1356 }
1357
Prabir Pradhan99987712020-11-10 18:43:05 -08001358 void consumeCaptureEvent(bool hasCapture) {
1359 ASSERT_NE(mInputReceiver, nullptr)
1360 << "Cannot consume events from a window with no receiver";
1361 mInputReceiver->consumeCaptureEvent(hasCapture);
1362 }
1363
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001364 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1365 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001366 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001367 ASSERT_THAT(*motionEvent, matcher);
1368 }
1369
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001370 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001371 std::optional<int32_t> expectedDisplayId,
1372 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001373 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1374 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1375 expectedFlags);
1376 }
1377
arthurhungb89ccb02020-12-30 16:19:01 +08001378 void consumeDragEvent(bool isExiting, float x, float y) {
1379 mInputReceiver->consumeDragEvent(isExiting, x, y);
1380 }
1381
Antonio Kantekf16f2832021-09-28 04:39:20 +00001382 void consumeTouchModeEvent(bool inTouchMode) {
1383 ASSERT_NE(mInputReceiver, nullptr)
1384 << "Cannot consume events from a window with no receiver";
1385 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1386 }
1387
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001388 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001389 if (mInputReceiver == nullptr) {
1390 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1391 return std::nullopt;
1392 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001393 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001394 }
1395
1396 void finishEvent(uint32_t sequenceNum) {
1397 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1398 mInputReceiver->finishEvent(sequenceNum);
1399 }
1400
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001401 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1402 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1403 mInputReceiver->sendTimeline(inputEventId, timeline);
1404 }
1405
chaviwaf87b3e2019-10-01 16:59:28 -07001406 InputEvent* consume() {
1407 if (mInputReceiver == nullptr) {
1408 return nullptr;
1409 }
1410 return mInputReceiver->consume();
1411 }
1412
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001413 MotionEvent* consumeMotion() {
1414 InputEvent* event = consume();
1415 if (event == nullptr) {
1416 ADD_FAILURE() << "Consume failed : no event";
1417 return nullptr;
1418 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001419 if (event->getType() != InputEventType::MOTION) {
1420 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001421 return nullptr;
1422 }
1423 return static_cast<MotionEvent*>(event);
1424 }
1425
Arthur Hungb92218b2018-08-14 12:00:21 +08001426 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001427 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001428 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001429 return; // Can't receive events if the window does not have input channel
1430 }
1431 ASSERT_NE(nullptr, mInputReceiver)
1432 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001433 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001434 }
1435
chaviwaf87b3e2019-10-01 16:59:28 -07001436 sp<IBinder> getToken() { return mInfo.token; }
1437
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001438 const std::string& getName() { return mName; }
1439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001440 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001441 mInfo.ownerPid = ownerPid;
1442 mInfo.ownerUid = ownerUid;
1443 }
1444
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001445 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001446
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001447 void destroyReceiver() { mInputReceiver = nullptr; }
1448
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001449 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1450
chaviwd1c23182019-12-20 18:44:56 -08001451private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001452 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001453 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001454 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001455 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001456 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001457};
1458
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001459std::atomic<int32_t> FakeWindowHandle::sId{1};
1460
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001461static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001462 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001463 int32_t displayId = ADISPLAY_ID_NONE,
1464 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001465 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001466 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001467 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001468 KeyEvent event;
1469 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1470
1471 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001472 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001473 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1474 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001475
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001476 if (!allowKeyRepeat) {
1477 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1478 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001479 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001480 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001481}
1482
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001483static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001484 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001485 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001486}
1487
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001488// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1489// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1490// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001491static InputEventInjectionResult injectKeyDownNoRepeat(
1492 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001493 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001494 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001495 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496}
1497
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001498static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001500 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001501}
1502
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001503static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001504 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001505 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001506 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001507 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001508 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1509 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001510}
1511
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001512static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001513 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001514 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001515 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001516 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1517 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001518 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001519 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001520 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001521 MotionEventBuilder motionBuilder =
1522 MotionEventBuilder(action, source)
1523 .displayId(displayId)
1524 .eventTime(eventTime)
1525 .rawXCursorPosition(cursorPosition.x)
1526 .rawYCursorPosition(cursorPosition.y)
1527 .pointer(
1528 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1529 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1530 motionBuilder.downTime(eventTime);
1531 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001532
1533 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001534 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1535 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001536}
1537
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001538static InputEventInjectionResult injectMotionDown(
1539 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1540 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001541 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001542}
1543
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001544static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001545 int32_t source, int32_t displayId,
1546 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001547 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001548}
1549
Jackal Guof9696682018-10-05 12:23:23 +08001550static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1551 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1552 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001553 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001554 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1555 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001556
1557 return args;
1558}
1559
Josep del Riob3981622023-04-18 15:49:45 +00001560static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1561 int32_t displayId = ADISPLAY_ID_NONE) {
1562 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1563 // Define a valid key event.
1564 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001565 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001566 currentTime);
1567
1568 return args;
1569}
1570
1571static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1572 int32_t displayId = ADISPLAY_ID_NONE) {
1573 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1574 // Define a valid key event.
1575 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001576 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001577 AMETA_NONE, currentTime);
1578
1579 return args;
1580}
1581
Prabir Pradhan678438e2023-04-13 19:32:51 +00001582[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1583 int32_t displayId,
1584 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001585 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001586 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1587 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1588 }
1589
chaviwd1c23182019-12-20 18:44:56 -08001590 PointerProperties pointerProperties[pointerCount];
1591 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001592
chaviwd1c23182019-12-20 18:44:56 -08001593 for (size_t i = 0; i < pointerCount; i++) {
1594 pointerProperties[i].clear();
1595 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001596 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001597
chaviwd1c23182019-12-20 18:44:56 -08001598 pointerCoords[i].clear();
1599 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1600 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1601 }
Jackal Guof9696682018-10-05 12:23:23 +08001602
1603 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1604 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001605 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001606 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1607 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001608 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001609 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001610 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001611 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001612
1613 return args;
1614}
1615
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001616static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1617 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1618}
1619
chaviwd1c23182019-12-20 18:44:56 -08001620static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1621 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1622}
1623
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001624static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1625 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001626 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001627}
1628
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001629} // namespace
1630
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001631/**
1632 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1633 * broken channel.
1634 */
1635TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1637 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001638 sp<FakeWindowHandle>::make(application, mDispatcher,
1639 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001640
1641 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1642
1643 // Window closes its channel, but the window remains.
1644 window->destroyReceiver();
1645 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1646}
1647
Arthur Hungb92218b2018-08-14 12:00:21 +08001648TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001650 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1651 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001652
Arthur Hung72d8dc32020-03-28 00:48:39 +00001653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1655 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001657
1658 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001659 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001660}
1661
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001662TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001664 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1665 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001666
1667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1668 // Inject a MotionEvent to an unknown display.
1669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1670 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1672
1673 // Window should receive motion event.
1674 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1675}
1676
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001678 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001679 * This test serves as a sanity check for the next test, where setInputWindows is
1680 * called twice.
1681 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001682TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001684 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1685 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001686 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687
1688 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1691 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693
1694 // Window should receive motion event.
1695 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1696}
1697
1698/**
1699 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001700 */
1701TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1704 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001705 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706
1707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1708 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1711 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713
1714 // Window should receive motion event.
1715 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1716}
1717
Arthur Hungb92218b2018-08-14 12:00:21 +08001718// The foreground window should receive the first touch down event.
1719TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001721 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001722 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001723 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001724 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001725
Arthur Hung72d8dc32020-03-28 00:48:39 +00001726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1728 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001730
1731 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001732 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001733 windowSecond->assertNoEvents();
1734}
1735
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001736/**
1737 * Two windows: A top window, and a wallpaper behind the window.
1738 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1739 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001740 * 1. foregroundWindow <-- dup touch to wallpaper
1741 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001742 */
1743TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1745 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001746 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001747 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001748 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001750 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001751
1752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1754 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1755 {100, 200}))
1756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1757
1758 // Both foreground window and its wallpaper should receive the touch down
1759 foregroundWindow->consumeMotionDown();
1760 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1761
1762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1763 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1764 ADISPLAY_ID_DEFAULT, {110, 200}))
1765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1766
1767 foregroundWindow->consumeMotionMove();
1768 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1769
1770 // Now the foreground window goes away, but the wallpaper stays
1771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1772 foregroundWindow->consumeMotionCancel();
1773 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1774 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1775}
1776
1777/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001778 * Two fingers down on the window, and lift off the first finger.
1779 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1780 * contains a single pointer.
1781 */
1782TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1783 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1784 sp<FakeWindowHandle> window =
1785 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1786
1787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001788 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1790 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1791 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001792 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001793 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1794 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1795 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1796 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001797 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001798 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1799 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1800 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1801 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001802 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1803 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1804 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1805
1806 // Remove the window. The gesture should be canceled
1807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1808 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1809 window->consumeMotionEvent(
1810 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1811}
1812
1813/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001814 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1815 * with the following differences:
1816 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1817 * clean up the connection.
1818 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1819 * Ensure that there's no crash in the dispatcher.
1820 */
1821TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1823 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001824 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001825 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001827 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001828 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001829
1830 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1832 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1833 {100, 200}))
1834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1835
1836 // Both foreground window and its wallpaper should receive the touch down
1837 foregroundWindow->consumeMotionDown();
1838 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1839
1840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1841 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1842 ADISPLAY_ID_DEFAULT, {110, 200}))
1843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1844
1845 foregroundWindow->consumeMotionMove();
1846 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1847
1848 // Wallpaper closes its channel, but the window remains.
1849 wallpaperWindow->destroyReceiver();
1850 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1851
1852 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1853 // is no longer valid.
1854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1855 foregroundWindow->consumeMotionCancel();
1856}
1857
Arthur Hungc539dbb2022-12-08 07:45:36 +00001858class ShouldSplitTouchFixture : public InputDispatcherTest,
1859 public ::testing::WithParamInterface<bool> {};
1860INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1861 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001863 * A single window that receives touch (on top), and a wallpaper window underneath it.
1864 * The top window gets a multitouch gesture.
1865 * Ensure that wallpaper gets the same gesture.
1866 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001867TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001869 sp<FakeWindowHandle> foregroundWindow =
1870 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1871 foregroundWindow->setDupTouchToWallpaper(true);
1872 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001873
1874 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001875 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001876 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877
Arthur Hungc539dbb2022-12-08 07:45:36 +00001878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879
1880 // Touch down on top window
1881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1882 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1883 {100, 100}))
1884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1885
1886 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1889
1890 // Second finger down on the top window
1891 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001892 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001894 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1895 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 .build();
1897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1898 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1899 InputEventInjectionSync::WAIT_FOR_RESULT))
1900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1901
Harry Cutts33476232023-01-30 19:57:29 +00001902 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1903 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001905
1906 const MotionEvent secondFingerUpEvent =
1907 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1908 .displayId(ADISPLAY_ID_DEFAULT)
1909 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001910 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1911 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001912 .build();
1913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1914 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1915 InputEventInjectionSync::WAIT_FOR_RESULT))
1916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1917 foregroundWindow->consumeMotionPointerUp(0);
1918 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1919
1920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001921 injectMotionEvent(mDispatcher,
1922 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1923 AINPUT_SOURCE_TOUCHSCREEN)
1924 .displayId(ADISPLAY_ID_DEFAULT)
1925 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001926 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001927 .x(100)
1928 .y(100))
1929 .build(),
1930 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1932 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1933 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934}
1935
1936/**
1937 * Two windows: a window on the left and window on the right.
1938 * A third window, wallpaper, is behind both windows, and spans both top windows.
1939 * The first touch down goes to the left window. A second pointer touches down on the right window.
1940 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1941 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1942 * ACTION_POINTER_DOWN(1).
1943 */
1944TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1946 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001947 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001949 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950
1951 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001952 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001953 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001954 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955
1956 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001957 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001959 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960
1961 mDispatcher->setInputWindows(
1962 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1963
1964 // Touch down on left window
1965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1966 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1967 {100, 100}))
1968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1969
1970 // Both foreground window and its wallpaper should receive the touch down
1971 leftWindow->consumeMotionDown();
1972 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1973
1974 // Second finger down on the right window
1975 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001976 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001978 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1979 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980 .build();
1981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1982 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1983 InputEventInjectionSync::WAIT_FOR_RESULT))
1984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1985
1986 leftWindow->consumeMotionMove();
1987 // Since the touch is split, right window gets ACTION_DOWN
1988 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001989 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990 expectedWallpaperFlags);
1991
1992 // Now, leftWindow, which received the first finger, disappears.
1993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1994 leftWindow->consumeMotionCancel();
1995 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1996 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1997
1998 // The pointer that's still down on the right window moves, and goes to the right window only.
1999 // As far as the dispatcher's concerned though, both pointers are still present.
2000 const MotionEvent secondFingerMoveEvent =
2001 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2002 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002003 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2004 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002005 .build();
2006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2007 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2008 InputEventInjectionSync::WAIT_FOR_RESULT));
2009 rightWindow->consumeMotionMove();
2010
2011 leftWindow->assertNoEvents();
2012 rightWindow->assertNoEvents();
2013 wallpaperWindow->assertNoEvents();
2014}
2015
Arthur Hungc539dbb2022-12-08 07:45:36 +00002016/**
2017 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2018 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2019 * The right window should receive ACTION_DOWN.
2020 */
2021TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002023 sp<FakeWindowHandle> leftWindow =
2024 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2025 leftWindow->setFrame(Rect(0, 0, 200, 200));
2026 leftWindow->setDupTouchToWallpaper(true);
2027 leftWindow->setSlippery(true);
2028
2029 sp<FakeWindowHandle> rightWindow =
2030 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2031 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002032
2033 sp<FakeWindowHandle> wallpaperWindow =
2034 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2035 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002036
Arthur Hungc539dbb2022-12-08 07:45:36 +00002037 mDispatcher->setInputWindows(
2038 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002039
Arthur Hungc539dbb2022-12-08 07:45:36 +00002040 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2042 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045
2046 // Both foreground window and its wallpaper should receive the touch down
2047 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002048 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2049
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2053 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2055
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 leftWindow->consumeMotionCancel();
2057 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2058 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002059}
2060
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002061/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002062 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2063 * interactive, it might stop sending this flag.
2064 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2065 * to have a consistent input stream.
2066 *
2067 * Test procedure:
2068 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2069 * DOWN (new gesture).
2070 *
2071 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2072 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2073 *
2074 * We technically just need a single window here, but we are using two windows (spy on top and a
2075 * regular window below) to emulate the actual situation where it happens on the device.
2076 */
2077TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2079 sp<FakeWindowHandle> spyWindow =
2080 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2081 spyWindow->setFrame(Rect(0, 0, 200, 200));
2082 spyWindow->setTrustedOverlay(true);
2083 spyWindow->setSpy(true);
2084
2085 sp<FakeWindowHandle> window =
2086 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2087 window->setFrame(Rect(0, 0, 200, 200));
2088
2089 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2090 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002091
2092 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002093 mDispatcher->notifyMotion(
2094 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2095 .deviceId(touchDeviceId)
2096 .policyFlags(DEFAULT_POLICY_FLAGS)
2097 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2098 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002099
Prabir Pradhan678438e2023-04-13 19:32:51 +00002100 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2101 .deviceId(touchDeviceId)
2102 .policyFlags(DEFAULT_POLICY_FLAGS)
2103 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2104 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2105 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2107 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2108 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2109 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2110
2111 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002112 mDispatcher->notifyMotion(
2113 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2114 .deviceId(touchDeviceId)
2115 .policyFlags(0)
2116 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2117 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2118 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002119 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2120 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2121
2122 // We don't need to reset the device to reproduce the issue, but the reset event typically
2123 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002124 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002125
2126 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002127 mDispatcher->notifyMotion(
2128 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2129 .deviceId(touchDeviceId)
2130 .policyFlags(DEFAULT_POLICY_FLAGS)
2131 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2132 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002133 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2134 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2135
2136 // No more events
2137 spyWindow->assertNoEvents();
2138 window->assertNoEvents();
2139}
2140
2141/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002142 * Two windows: a window on the left and a window on the right.
2143 * Mouse is hovered from the right window into the left window.
2144 * Next, we tap on the left window, where the cursor was last seen.
2145 * The second tap is done onto the right window.
2146 * The mouse and tap are from two different devices.
2147 * We technically don't need to set the downtime / eventtime for these events, but setting these
2148 * explicitly helps during debugging.
2149 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2150 * In the buggy implementation, a tap on the right window would cause a crash.
2151 */
2152TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2153 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2154 sp<FakeWindowHandle> leftWindow =
2155 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2156 leftWindow->setFrame(Rect(0, 0, 200, 200));
2157
2158 sp<FakeWindowHandle> rightWindow =
2159 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2160 rightWindow->setFrame(Rect(200, 0, 400, 200));
2161
2162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2163 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2164 // stale.
2165 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2166 const int32_t mouseDeviceId = 6;
2167 const int32_t touchDeviceId = 4;
2168 // Move the cursor from right
2169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2170 injectMotionEvent(mDispatcher,
2171 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2172 AINPUT_SOURCE_MOUSE)
2173 .deviceId(mouseDeviceId)
2174 .downTime(baseTime + 10)
2175 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002176 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002177 .x(300)
2178 .y(100))
2179 .build()));
2180 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2181
2182 // .. to the left window
2183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2184 injectMotionEvent(mDispatcher,
2185 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2186 AINPUT_SOURCE_MOUSE)
2187 .deviceId(mouseDeviceId)
2188 .downTime(baseTime + 10)
2189 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002190 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002191 .x(110)
2192 .y(100))
2193 .build()));
2194 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2195 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2196 // Now tap the left window
2197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2198 injectMotionEvent(mDispatcher,
2199 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2200 AINPUT_SOURCE_TOUCHSCREEN)
2201 .deviceId(touchDeviceId)
2202 .downTime(baseTime + 40)
2203 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002204 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002205 .x(100)
2206 .y(100))
2207 .build()));
2208 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2209 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2210
2211 // release tap
2212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2213 injectMotionEvent(mDispatcher,
2214 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2215 AINPUT_SOURCE_TOUCHSCREEN)
2216 .deviceId(touchDeviceId)
2217 .downTime(baseTime + 40)
2218 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002219 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002220 .x(100)
2221 .y(100))
2222 .build()));
2223 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2224
2225 // Tap the window on the right
2226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2227 injectMotionEvent(mDispatcher,
2228 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2229 AINPUT_SOURCE_TOUCHSCREEN)
2230 .deviceId(touchDeviceId)
2231 .downTime(baseTime + 60)
2232 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002233 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002234 .x(300)
2235 .y(100))
2236 .build()));
2237 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2238
2239 // release tap
2240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2241 injectMotionEvent(mDispatcher,
2242 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2243 AINPUT_SOURCE_TOUCHSCREEN)
2244 .deviceId(touchDeviceId)
2245 .downTime(baseTime + 60)
2246 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002247 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 .x(300)
2249 .y(100))
2250 .build()));
2251 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2252
2253 // No more events
2254 leftWindow->assertNoEvents();
2255 rightWindow->assertNoEvents();
2256}
2257
2258/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002259 * Start hovering in a window. While this hover is still active, make another window appear on top.
2260 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2261 * While the top window is present, the hovering is stopped.
2262 * Later, hovering gets resumed again.
2263 * Ensure that new hover gesture is handled correctly.
2264 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2265 * to the window that's currently being hovered over.
2266 */
2267TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2269 sp<FakeWindowHandle> window =
2270 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2271 window->setFrame(Rect(0, 0, 200, 200));
2272
2273 // Only a single window is present at first
2274 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2275
2276 // Start hovering in the window
2277 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2278 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2279 .build());
2280 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2281
2282 // Now, an obscuring window appears!
2283 sp<FakeWindowHandle> obscuringWindow =
2284 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2285 ADISPLAY_ID_DEFAULT,
2286 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2287 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2288 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2289 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2290 obscuringWindow->setNoInputChannel(true);
2291 obscuringWindow->setFocusable(false);
2292 obscuringWindow->setAlpha(1.0);
2293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2294
2295 // While this new obscuring window is present, the hovering is stopped
2296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2297 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2298 .build());
2299 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2300
2301 // Now the obscuring window goes away.
2302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2303
2304 // And a new hover gesture starts.
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2307 .build());
2308 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2309}
2310
2311/**
2312 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2313 * the obscuring window.
2314 */
2315TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2317 sp<FakeWindowHandle> window =
2318 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2319 window->setFrame(Rect(0, 0, 200, 200));
2320
2321 // Only a single window is present at first
2322 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2323
2324 // Start hovering in the window
2325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2326 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2327 .build());
2328 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2329
2330 // Now, an obscuring window appears!
2331 sp<FakeWindowHandle> obscuringWindow =
2332 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2333 ADISPLAY_ID_DEFAULT,
2334 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2335 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2336 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2337 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2338 obscuringWindow->setNoInputChannel(true);
2339 obscuringWindow->setFocusable(false);
2340 obscuringWindow->setAlpha(1.0);
2341 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2342
2343 // While this new obscuring window is present, the hovering continues. The event can't go to the
2344 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2345 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2346 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2347 .build());
2348 obscuringWindow->assertNoEvents();
2349 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2350
2351 // Now the obscuring window goes away.
2352 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2353
2354 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2355 // so it should generate a HOVER_ENTER
2356 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2357 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2358 .build());
2359 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2360
2361 // Now the MOVE should be getting dispatched normally
2362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2363 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2364 .build());
2365 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2366}
2367
2368/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002369 * Two windows: a window on the left and a window on the right.
2370 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2371 * down. Then, on the left window, also place second touch pointer down.
2372 * This test tries to reproduce a crash.
2373 * In the buggy implementation, second pointer down on the left window would cause a crash.
2374 */
2375TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2377 sp<FakeWindowHandle> leftWindow =
2378 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2379 leftWindow->setFrame(Rect(0, 0, 200, 200));
2380
2381 sp<FakeWindowHandle> rightWindow =
2382 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2383 rightWindow->setFrame(Rect(200, 0, 400, 200));
2384
2385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2386
2387 const int32_t touchDeviceId = 4;
2388 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002389
2390 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2392 .deviceId(mouseDeviceId)
2393 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2394 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002395 leftWindow->consumeMotionEvent(
2396 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2397
2398 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2400 .deviceId(mouseDeviceId)
2401 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2402 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2403 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002404
2405 leftWindow->consumeMotionEvent(
2406 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2407 leftWindow->consumeMotionEvent(
2408 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2409
Prabir Pradhan678438e2023-04-13 19:32:51 +00002410 mDispatcher->notifyMotion(
2411 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2412 .deviceId(mouseDeviceId)
2413 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2414 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2415 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2416 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002417 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2418
2419 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002420 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2421 .deviceId(touchDeviceId)
2422 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2423 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002424 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2425
2426 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2427
2428 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002429 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2430 .deviceId(touchDeviceId)
2431 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2432 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2433 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002434 leftWindow->consumeMotionEvent(
2435 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2436 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2437 // current implementation.
2438 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2439 rightWindow->consumeMotionEvent(
2440 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2441
2442 leftWindow->assertNoEvents();
2443 rightWindow->assertNoEvents();
2444}
2445
2446/**
2447 * On a single window, use two different devices: mouse and touch.
2448 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2449 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2450 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2451 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2452 * represent a new gesture.
2453 */
2454TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2455 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2456 sp<FakeWindowHandle> window =
2457 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2458 window->setFrame(Rect(0, 0, 400, 400));
2459
2460 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2461
2462 const int32_t touchDeviceId = 4;
2463 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002464
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002465 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2467 .deviceId(touchDeviceId)
2468 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2469 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002470 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002471 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2472 .deviceId(touchDeviceId)
2473 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2474 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2475 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002476 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002477 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2478 .deviceId(touchDeviceId)
2479 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2480 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002482 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2483 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2484 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2485
2486 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2488 .deviceId(mouseDeviceId)
2489 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2490 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2491 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002492
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002494 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002495 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2496
Prabir Pradhan678438e2023-04-13 19:32:51 +00002497 mDispatcher->notifyMotion(
2498 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2499 .deviceId(mouseDeviceId)
2500 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2501 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2502 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2503 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002504 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2505
2506 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002507 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2508 .deviceId(touchDeviceId)
2509 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2510 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2511 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002512 // The pointer_down event should be ignored
2513 window->assertNoEvents();
2514}
2515
2516/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002517 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2518 * the injected event.
2519 */
2520TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2521 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2522 sp<FakeWindowHandle> window =
2523 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2524 window->setFrame(Rect(0, 0, 400, 400));
2525
2526 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2527
2528 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002529 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2530 // completion.
2531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2532 injectMotionEvent(mDispatcher,
2533 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2534 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002535 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002536 .x(50)
2537 .y(50))
2538 .build()));
2539 window->consumeMotionEvent(
2540 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2541
2542 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2543 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002544 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2545 .deviceId(touchDeviceId)
2546 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2547 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002548
2549 window->consumeMotionEvent(
2550 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2552}
2553
2554/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002555 * This test is similar to the test above, but the sequence of injected events is different.
2556 *
2557 * Two windows: a window on the left and a window on the right.
2558 * Mouse is hovered over the left window.
2559 * Next, we tap on the left window, where the cursor was last seen.
2560 *
2561 * After that, we inject one finger down onto the right window, and then a second finger down onto
2562 * the left window.
2563 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2564 * window (first), and then another on the left window (second).
2565 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2566 * In the buggy implementation, second finger down on the left window would cause a crash.
2567 */
2568TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2570 sp<FakeWindowHandle> leftWindow =
2571 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2572 leftWindow->setFrame(Rect(0, 0, 200, 200));
2573
2574 sp<FakeWindowHandle> rightWindow =
2575 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2576 rightWindow->setFrame(Rect(200, 0, 400, 200));
2577
2578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2579
2580 const int32_t mouseDeviceId = 6;
2581 const int32_t touchDeviceId = 4;
2582 // Hover over the left window. Keep the cursor there.
2583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2584 injectMotionEvent(mDispatcher,
2585 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2586 AINPUT_SOURCE_MOUSE)
2587 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002588 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002589 .x(50)
2590 .y(50))
2591 .build()));
2592 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2593
2594 // Tap on left window
2595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2596 injectMotionEvent(mDispatcher,
2597 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2598 AINPUT_SOURCE_TOUCHSCREEN)
2599 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002600 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002601 .x(100)
2602 .y(100))
2603 .build()));
2604
2605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2606 injectMotionEvent(mDispatcher,
2607 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2608 AINPUT_SOURCE_TOUCHSCREEN)
2609 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002610 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002611 .x(100)
2612 .y(100))
2613 .build()));
2614 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2615 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2616 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2617
2618 // First finger down on right window
2619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2620 injectMotionEvent(mDispatcher,
2621 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2622 AINPUT_SOURCE_TOUCHSCREEN)
2623 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002624 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002625 .x(300)
2626 .y(100))
2627 .build()));
2628 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2629
2630 // Second finger down on the left window
2631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2632 injectMotionEvent(mDispatcher,
2633 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2634 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002635 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002636 .x(300)
2637 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002638 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002639 .x(100)
2640 .y(100))
2641 .build()));
2642 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2643 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2644
2645 // No more events
2646 leftWindow->assertNoEvents();
2647 rightWindow->assertNoEvents();
2648}
2649
2650/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002651 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2652 * While the touch is down, new hover events from the stylus device should be ignored. After the
2653 * touch is gone, stylus hovering should start working again.
2654 */
2655TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2657 sp<FakeWindowHandle> window =
2658 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2659 window->setFrame(Rect(0, 0, 200, 200));
2660
2661 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2662
2663 const int32_t stylusDeviceId = 5;
2664 const int32_t touchDeviceId = 4;
2665 // Start hovering with stylus
2666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2667 injectMotionEvent(mDispatcher,
2668 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2669 AINPUT_SOURCE_STYLUS)
2670 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002671 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002672 .x(50)
2673 .y(50))
2674 .build()));
2675 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2676
2677 // Finger down on the window
2678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2679 injectMotionEvent(mDispatcher,
2680 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2681 AINPUT_SOURCE_TOUCHSCREEN)
2682 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002683 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002684 .x(100)
2685 .y(100))
2686 .build()));
2687 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2688 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2689
2690 // Try to continue hovering with stylus. Since we are already down, injection should fail
2691 ASSERT_EQ(InputEventInjectionResult::FAILED,
2692 injectMotionEvent(mDispatcher,
2693 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2694 AINPUT_SOURCE_STYLUS)
2695 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002696 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002697 .build()));
2698 // No event should be sent. This event should be ignored because a pointer from another device
2699 // is already down.
2700
2701 // Lift up the finger
2702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2703 injectMotionEvent(mDispatcher,
2704 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2705 AINPUT_SOURCE_TOUCHSCREEN)
2706 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002707 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002708 .x(100)
2709 .y(100))
2710 .build()));
2711 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2712
2713 // Now that the touch is gone, stylus hovering should start working again
2714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2715 injectMotionEvent(mDispatcher,
2716 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2717 AINPUT_SOURCE_STYLUS)
2718 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002719 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002720 .build()));
2721 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2722 // No more events
2723 window->assertNoEvents();
2724}
2725
2726/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002727 * A spy window above a window with no input channel.
2728 * Start hovering with a stylus device, and then tap with it.
2729 * Ensure spy window receives the entire sequence.
2730 */
2731TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2733 sp<FakeWindowHandle> spyWindow =
2734 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2735 spyWindow->setFrame(Rect(0, 0, 200, 200));
2736 spyWindow->setTrustedOverlay(true);
2737 spyWindow->setSpy(true);
2738 sp<FakeWindowHandle> window =
2739 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2740 window->setNoInputChannel(true);
2741 window->setFrame(Rect(0, 0, 200, 200));
2742
2743 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2744
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002745 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2748 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002749 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2750 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002751 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2753 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002754 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2755
2756 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2758 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2759 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002760 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2761
2762 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2764 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2765 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002766 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2767
2768 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2770 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2771 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002772 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2773 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2776 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002777 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2778
2779 // No more events
2780 spyWindow->assertNoEvents();
2781 window->assertNoEvents();
2782}
2783
2784/**
2785 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2786 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2787 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2788 * While the mouse is down, new move events from the touch device should be ignored.
2789 */
2790TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2791 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2792 sp<FakeWindowHandle> spyWindow =
2793 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2794 spyWindow->setFrame(Rect(0, 0, 200, 200));
2795 spyWindow->setTrustedOverlay(true);
2796 spyWindow->setSpy(true);
2797 sp<FakeWindowHandle> window =
2798 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2799 window->setFrame(Rect(0, 0, 200, 200));
2800
2801 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2802
2803 const int32_t mouseDeviceId = 7;
2804 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002805
2806 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002807 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2808 .deviceId(mouseDeviceId)
2809 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2810 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002811 spyWindow->consumeMotionEvent(
2812 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2813 window->consumeMotionEvent(
2814 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2815
2816 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2818 .deviceId(touchDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2820 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2822 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2823 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2824 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2825
Prabir Pradhan678438e2023-04-13 19:32:51 +00002826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2827 .deviceId(touchDeviceId)
2828 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2829 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002830 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2831 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2832
2833 // Pilfer the stream
2834 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2835 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2836
Prabir Pradhan678438e2023-04-13 19:32:51 +00002837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2838 .deviceId(touchDeviceId)
2839 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2840 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002841 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2842
2843 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2845 .deviceId(mouseDeviceId)
2846 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2847 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2848 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002849
2850 spyWindow->consumeMotionEvent(
2851 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2852 spyWindow->consumeMotionEvent(
2853 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2854 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2855
Prabir Pradhan678438e2023-04-13 19:32:51 +00002856 mDispatcher->notifyMotion(
2857 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2858 .deviceId(mouseDeviceId)
2859 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2860 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2861 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2862 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002863 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2864 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2865
2866 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2868 .deviceId(mouseDeviceId)
2869 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2870 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2871 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002872 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2873 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2874
2875 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2877 .deviceId(touchDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2879 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002880
2881 // No more events
2882 spyWindow->assertNoEvents();
2883 window->assertNoEvents();
2884}
2885
2886/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002887 * On the display, have a single window, and also an area where there's no window.
2888 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2889 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2890 */
2891TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2893 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002894 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002895
2896 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002897
2898 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002899 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002900
2901 mDispatcher->waitForIdle();
2902 window->assertNoEvents();
2903
2904 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002905 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002906 mDispatcher->waitForIdle();
2907 window->consumeMotionDown();
2908}
2909
2910/**
2911 * Same test as above, but instead of touching the empty space, the first touch goes to
2912 * non-touchable window.
2913 */
2914TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2916 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002917 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002918 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2919 window1->setTouchable(false);
2920 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002921 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002922 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2923
2924 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2925
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002926 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002927 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002928
2929 mDispatcher->waitForIdle();
2930 window1->assertNoEvents();
2931 window2->assertNoEvents();
2932
2933 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002934 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002935 mDispatcher->waitForIdle();
2936 window2->consumeMotionDown();
2937}
2938
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002939/**
2940 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2941 * to the event time of the first ACTION_DOWN sent to the particular window.
2942 */
2943TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2945 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002946 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002947 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2948 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002949 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002950 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2951
2952 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2953
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002954 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002955 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002956
2957 mDispatcher->waitForIdle();
2958 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002959 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002960 window2->assertNoEvents();
2961 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2962 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2963 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2964
2965 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002966 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002967 mDispatcher->waitForIdle();
2968 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002969 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002970 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2971 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2972 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2973 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2974
2975 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002976 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002978 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002979
2980 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002981 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002982 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002983 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002984
2985 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2986 window1->consumeMotionMove();
2987 window1->assertNoEvents();
2988
2989 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002990 mDispatcher->notifyMotion(
2991 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002992 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002993 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002994
Prabir Pradhan678438e2023-04-13 19:32:51 +00002995 mDispatcher->notifyMotion(
2996 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002997 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002998 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002999}
3000
Garfield Tandf26e862020-07-01 20:18:19 -07003001TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003003 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003004 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003005 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003006 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003007 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003008 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003009
3010 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3011
3012 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3013
3014 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003016 injectMotionEvent(mDispatcher,
3017 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3018 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003019 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003020 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003021 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003022
3023 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003025 injectMotionEvent(mDispatcher,
3026 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3027 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003028 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003029 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003030 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3031 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003032
3033 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003035 injectMotionEvent(mDispatcher,
3036 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3037 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003038 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003039 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003040 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3041 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003044 injectMotionEvent(mDispatcher,
3045 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3046 AINPUT_SOURCE_MOUSE)
3047 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3048 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003049 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003050 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003051 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003052
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003054 injectMotionEvent(mDispatcher,
3055 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3056 AINPUT_SOURCE_MOUSE)
3057 .buttonState(0)
3058 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003059 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003060 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003061 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003062
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003064 injectMotionEvent(mDispatcher,
3065 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3066 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003067 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003068 .build()));
3069 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3070
3071 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003073 injectMotionEvent(mDispatcher,
3074 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3075 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003076 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003077 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003078 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003079
3080 // No more events
3081 windowLeft->assertNoEvents();
3082 windowRight->assertNoEvents();
3083}
3084
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003085/**
3086 * Put two fingers down (and don't release them) and click the mouse button.
3087 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3088 * currently active gesture should be canceled, and the new one should proceed.
3089 */
3090TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3092 sp<FakeWindowHandle> window =
3093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3094 window->setFrame(Rect(0, 0, 600, 800));
3095
3096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3097
3098 const int32_t touchDeviceId = 4;
3099 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100
3101 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003102 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3110 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3113 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3114
3115 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3117 .deviceId(mouseDeviceId)
3118 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3119 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3120 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003121 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3122 WithPointerCount(2u)));
3123 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3124
Prabir Pradhan678438e2023-04-13 19:32:51 +00003125 mDispatcher->notifyMotion(
3126 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3127 .deviceId(mouseDeviceId)
3128 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3129 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3131 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003132 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3133
3134 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3135 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003136 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3137 .deviceId(touchDeviceId)
3138 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3139 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3140 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003141 window->assertNoEvents();
3142}
3143
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003144TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3145 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3146
3147 sp<FakeWindowHandle> spyWindow =
3148 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3149 spyWindow->setFrame(Rect(0, 0, 600, 800));
3150 spyWindow->setTrustedOverlay(true);
3151 spyWindow->setSpy(true);
3152 sp<FakeWindowHandle> window =
3153 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3154 window->setFrame(Rect(0, 0, 600, 800));
3155
3156 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3157 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3158
3159 // Send mouse cursor to the window
3160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3161 injectMotionEvent(mDispatcher,
3162 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3163 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003164 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003165 .x(100)
3166 .y(100))
3167 .build()));
3168
3169 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3170 WithSource(AINPUT_SOURCE_MOUSE)));
3171 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3172 WithSource(AINPUT_SOURCE_MOUSE)));
3173
3174 window->assertNoEvents();
3175 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003176}
3177
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003178TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3179 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3180
3181 sp<FakeWindowHandle> spyWindow =
3182 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3183 spyWindow->setFrame(Rect(0, 0, 600, 800));
3184 spyWindow->setTrustedOverlay(true);
3185 spyWindow->setSpy(true);
3186 sp<FakeWindowHandle> window =
3187 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3188 window->setFrame(Rect(0, 0, 600, 800));
3189
3190 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3191 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3192
3193 // Send mouse cursor to the window
3194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3195 injectMotionEvent(mDispatcher,
3196 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3197 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003198 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003199 .x(100)
3200 .y(100))
3201 .build()));
3202
3203 // Move mouse cursor
3204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3205 injectMotionEvent(mDispatcher,
3206 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3207 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003208 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003209 .x(110)
3210 .y(110))
3211 .build()));
3212
3213 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3214 WithSource(AINPUT_SOURCE_MOUSE)));
3215 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3216 WithSource(AINPUT_SOURCE_MOUSE)));
3217 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3218 WithSource(AINPUT_SOURCE_MOUSE)));
3219 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3220 WithSource(AINPUT_SOURCE_MOUSE)));
3221 // Touch down on the window
3222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3223 injectMotionEvent(mDispatcher,
3224 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3225 AINPUT_SOURCE_TOUCHSCREEN)
3226 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003227 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003228 .x(200)
3229 .y(200))
3230 .build()));
3231 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3232 WithSource(AINPUT_SOURCE_MOUSE)));
3233 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3234 WithSource(AINPUT_SOURCE_MOUSE)));
3235 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3236 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3237 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3238 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3239
3240 // pilfer the motion, retaining the gesture on the spy window.
3241 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3242 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3243 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3244
3245 // Touch UP on the window
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3247 injectMotionEvent(mDispatcher,
3248 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003252 .x(200)
3253 .y(200))
3254 .build()));
3255 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3256 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3257
3258 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3259 // to send a new gesture. It should again go to both windows (spy and the window below), just
3260 // like the first gesture did, before pilfering. The window configuration has not changed.
3261
3262 // One more tap - DOWN
3263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3264 injectMotionEvent(mDispatcher,
3265 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3266 AINPUT_SOURCE_TOUCHSCREEN)
3267 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003268 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003269 .x(250)
3270 .y(250))
3271 .build()));
3272 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3273 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3274 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3275 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3276
3277 // Touch UP on the window
3278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3279 injectMotionEvent(mDispatcher,
3280 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3281 AINPUT_SOURCE_TOUCHSCREEN)
3282 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003283 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003284 .x(250)
3285 .y(250))
3286 .build()));
3287 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3288 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3289 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3290 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3291
3292 window->assertNoEvents();
3293 spyWindow->assertNoEvents();
3294}
3295
Garfield Tandf26e862020-07-01 20:18:19 -07003296// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3297// directly in this test.
3298TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003300 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003301 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003302 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003303
3304 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3305
3306 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3307
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003309 injectMotionEvent(mDispatcher,
3310 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3311 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003312 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003313 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003314 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003315 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003317 injectMotionEvent(mDispatcher,
3318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003321 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003322 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3323 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003326 injectMotionEvent(mDispatcher,
3327 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3328 AINPUT_SOURCE_MOUSE)
3329 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3330 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003331 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003332 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003333 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003334
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003336 injectMotionEvent(mDispatcher,
3337 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3338 AINPUT_SOURCE_MOUSE)
3339 .buttonState(0)
3340 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003342 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003343 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003346 injectMotionEvent(mDispatcher,
3347 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3348 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003349 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003350 .build()));
3351 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3352
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003353 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3354 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3355 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003356 injectMotionEvent(mDispatcher,
3357 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3358 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003359 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003360 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003361 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003362}
3363
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003364/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003365 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3366 * is generated.
3367 */
3368TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3369 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3370 sp<FakeWindowHandle> window =
3371 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3372 window->setFrame(Rect(0, 0, 1200, 800));
3373
3374 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3375
3376 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3377
3378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3379 injectMotionEvent(mDispatcher,
3380 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3381 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003382 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003383 .x(300)
3384 .y(400))
3385 .build()));
3386 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3387
3388 // Remove the window, but keep the channel.
3389 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3390 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3391}
3392
3393/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003394 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3395 */
3396TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3398 sp<FakeWindowHandle> window =
3399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3400 window->setFrame(Rect(0, 0, 100, 100));
3401
3402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3403
3404 const int32_t mouseDeviceId = 7;
3405 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003406
3407 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3409 .deviceId(mouseDeviceId)
3410 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3411 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003412 window->consumeMotionEvent(
3413 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3414
3415 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003416 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3417 .deviceId(touchDeviceId)
3418 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3419 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003420
3421 window->consumeMotionEvent(
3422 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3423 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3424}
3425
3426/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003427 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003428 * The tap causes a HOVER_EXIT event to be generated because the current event
3429 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003430 */
3431TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3433 sp<FakeWindowHandle> window =
3434 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3435 window->setFrame(Rect(0, 0, 100, 100));
3436
3437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3438
3439 // Inject a hover_move from mouse.
3440 NotifyMotionArgs motionArgs =
3441 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3442 ADISPLAY_ID_DEFAULT, {{50, 50}});
3443 motionArgs.xCursorPosition = 50;
3444 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003445 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003446 ASSERT_NO_FATAL_FAILURE(
3447 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3448 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003449
3450 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003451 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3452 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3453 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003454 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003455 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3456 WithSource(AINPUT_SOURCE_MOUSE))));
3457
3458 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003459 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3460 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3461
Prabir Pradhan678438e2023-04-13 19:32:51 +00003462 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3463 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003464 ASSERT_NO_FATAL_FAILURE(
3465 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3466 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3467}
3468
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003469TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3471 sp<FakeWindowHandle> windowDefaultDisplay =
3472 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3473 ADISPLAY_ID_DEFAULT);
3474 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3475 sp<FakeWindowHandle> windowSecondDisplay =
3476 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3477 SECOND_DISPLAY_ID);
3478 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3479
3480 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3481 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3482
3483 // Set cursor position in window in default display and check that hover enter and move
3484 // events are generated.
3485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3486 injectMotionEvent(mDispatcher,
3487 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3488 AINPUT_SOURCE_MOUSE)
3489 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003490 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003491 .x(300)
3492 .y(600))
3493 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003494 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003495
3496 // Remove all windows in secondary display and check that no event happens on window in
3497 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003498 mDispatcher->setInputWindows(
3499 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003500 windowDefaultDisplay->assertNoEvents();
3501
3502 // Move cursor position in window in default display and check that only hover move
3503 // event is generated and not hover enter event.
3504 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3505 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3507 injectMotionEvent(mDispatcher,
3508 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3509 AINPUT_SOURCE_MOUSE)
3510 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003511 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003512 .x(400)
3513 .y(700))
3514 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003515 windowDefaultDisplay->consumeMotionEvent(
3516 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3517 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003518 windowDefaultDisplay->assertNoEvents();
3519}
3520
Garfield Tan00f511d2019-06-12 16:55:40 -07003521TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003522 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003523
3524 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003525 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003526 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003527 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003528 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003529 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003530
3531 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3532
Arthur Hung72d8dc32020-03-28 00:48:39 +00003533 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
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
Arthur Hung72d8dc32020-03-28 00:48:39 +00003550 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
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
Arthur Hung72d8dc32020-03-28 00:48:39 +00003572 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
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
3592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3593
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
3617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3618 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
3642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3643 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
3677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3678
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});
3710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3711
3712 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003713 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3714 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3715 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003716 window->assertNoEvents();
3717 secondWindow->assertNoEvents();
3718
3719 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3720 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003721 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3722 ADISPLAY_ID_DEFAULT,
3723 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003724 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3725 window->consumeMotionEvent(
3726 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003727 secondWindow->consumeMotionDown();
3728 thirdWindow->assertNoEvents();
3729
3730 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3731 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003732 mDispatcher->notifyMotion(
3733 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3734 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003735 window->assertNoEvents();
3736 secondWindow->consumeMotionMove();
3737 thirdWindow->consumeMotionDown();
3738}
3739
Prabir Pradhan814fe082022-07-22 20:22:18 +00003740TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003742 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3743 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003744 window->setFocusable(true);
3745
Patrick Williamsd828f302023-04-28 17:52:08 -05003746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003747 setFocusedWindow(window);
3748
3749 window->consumeFocusEvent(true);
3750
Prabir Pradhan678438e2023-04-13 19:32:51 +00003751 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3752 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3753 mDispatcher->notifyKey(keyDown);
3754 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003755
3756 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3757 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3758
3759 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003760 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003761
3762 window->consumeFocusEvent(false);
3763
Prabir Pradhan678438e2023-04-13 19:32:51 +00003764 mDispatcher->notifyKey(keyDown);
3765 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003766 window->assertNoEvents();
3767}
3768
Arthur Hung96483742022-11-15 03:30:48 +00003769TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3771 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3772 "Fake Window", ADISPLAY_ID_DEFAULT);
3773 // Ensure window is non-split and have some transform.
3774 window->setPreventSplitting(true);
3775 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003776 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003777
3778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3779 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3780 {50, 50}))
3781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3782 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3783
3784 const MotionEvent secondFingerDownEvent =
3785 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3786 .displayId(ADISPLAY_ID_DEFAULT)
3787 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003788 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3789 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003790 .build();
3791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3792 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3793 InputEventInjectionSync::WAIT_FOR_RESULT))
3794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3795
3796 const MotionEvent* event = window->consumeMotion();
3797 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3798 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3799 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3800 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3801 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3802}
3803
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003804/**
3805 * Two windows: a splittable and a non-splittable.
3806 * The non-splittable window shouldn't receive any "incomplete" gestures.
3807 * Send the first pointer to the splittable window, and then touch the non-splittable window.
3808 * The second pointer should be dropped because the initial window is splittable, so it won't get
3809 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
3810 * "incomplete" gestures.
3811 */
3812TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
3813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3814 sp<FakeWindowHandle> leftWindow =
3815 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
3816 ADISPLAY_ID_DEFAULT);
3817 leftWindow->setPreventSplitting(false);
3818 leftWindow->setFrame(Rect(0, 0, 100, 100));
3819 sp<FakeWindowHandle> rightWindow =
3820 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
3821 ADISPLAY_ID_DEFAULT);
3822 rightWindow->setPreventSplitting(true);
3823 rightWindow->setFrame(Rect(100, 100, 200, 200));
3824 mDispatcher->onWindowInfosChanged(
3825 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3826
3827 // Touch down on left, splittable window
3828 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3829 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3830 .build());
3831 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3832
3833 mDispatcher->notifyMotion(
3834 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3835 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3836 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
3837 .build());
3838 leftWindow->assertNoEvents();
3839 rightWindow->assertNoEvents();
3840}
3841
Harry Cuttsb166c002023-05-09 13:06:05 +00003842TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3844 sp<FakeWindowHandle> window =
3845 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3846 window->setFrame(Rect(0, 0, 400, 400));
3847 sp<FakeWindowHandle> trustedOverlay =
3848 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3849 ADISPLAY_ID_DEFAULT);
3850 trustedOverlay->setSpy(true);
3851 trustedOverlay->setTrustedOverlay(true);
3852
3853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3854
3855 // Start a three-finger touchpad swipe
3856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3857 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3858 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3859 .build());
3860 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3861 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3862 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3863 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3864 .build());
3865 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3866 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3867 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3868 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3869 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3870 .build());
3871
3872 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3873 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3874 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3875
3876 // Move the swipe a bit
3877 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3878 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3879 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3880 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3881 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3882 .build());
3883
3884 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3885
3886 // End the swipe
3887 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3888 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3889 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3890 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3891 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3892 .build());
3893 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3894 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3895 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3896 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3897 .build());
3898 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3899 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3900 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3901 .build());
3902
3903 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3904 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3905 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3906
3907 window->assertNoEvents();
3908}
3909
3910TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3911 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3912 sp<FakeWindowHandle> window =
3913 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3914 window->setFrame(Rect(0, 0, 400, 400));
3915 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3916
3917 // Start a three-finger touchpad swipe
3918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3919 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3920 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3921 .build());
3922 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3923 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3924 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3925 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3926 .build());
3927 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3928 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3929 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3930 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3931 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3932 .build());
3933
3934 // Move the swipe a bit
3935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3936 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3937 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3938 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3939 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3940 .build());
3941
3942 // End the swipe
3943 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3944 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3945 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3946 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3947 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3948 .build());
3949 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3950 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3951 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3952 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3953 .build());
3954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3955 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3956 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3957 .build());
3958
3959 window->assertNoEvents();
3960}
3961
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003962/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003963 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3964 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003965 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003966 */
3967TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3968 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3969 sp<FakeWindowHandle> window =
3970 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3971 window->setFrame(Rect(0, 0, 400, 400));
3972 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3973
3974 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3976 .downTime(baseTime + 10)
3977 .eventTime(baseTime + 10)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3979 .build());
3980
3981 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3982
3983 // We need a new window object for the same window, because dispatcher will store objects by
3984 // reference. That means that the testing code and the dispatcher will refer to the same shared
3985 // object. Calling window->setTransform here would affect dispatcher's comparison
3986 // of the old window to the new window, since both the old window and the new window would be
3987 // updated to the same value.
3988 sp<FakeWindowHandle> windowDup = window->duplicate();
3989
3990 // Change the transform so that the orientation is now different from original.
3991 windowDup->setWindowTransform(0, -1, 1, 0);
3992
3993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3994
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003995 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3996 .downTime(baseTime + 10)
3997 .eventTime(baseTime + 30)
3998 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3999 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4000 .build());
4001
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004002 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4003
4004 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004005 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4006 .downTime(baseTime + 10)
4007 .eventTime(baseTime + 40)
4008 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4009 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4010 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004011
4012 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4013
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004014 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4015 .downTime(baseTime + 10)
4016 .eventTime(baseTime + 50)
4017 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4018 .build());
4019
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004020 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4021
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4023 .downTime(baseTime + 60)
4024 .eventTime(baseTime + 60)
4025 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4026 .build());
4027
4028 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4029}
4030
4031/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004032 * Ensure the correct coordinate spaces are used by InputDispatcher.
4033 *
4034 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4035 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4036 * space.
4037 */
4038class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4039public:
4040 void SetUp() override {
4041 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004042 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004043 }
4044
4045 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4046 gui::DisplayInfo info;
4047 info.displayId = displayId;
4048 info.transform = transform;
4049 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004050 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004051 }
4052
4053 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4054 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004055 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004056 }
4057
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004058 void removeAllWindowsAndDisplays() {
4059 mDisplayInfos.clear();
4060 mWindowInfos.clear();
4061 }
4062
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004063 // Set up a test scenario where the display has a scaled projection and there are two windows
4064 // on the display.
4065 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4066 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4067 // respectively.
4068 ui::Transform displayTransform;
4069 displayTransform.set(2, 0, 0, 4);
4070 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4071
4072 std::shared_ptr<FakeApplicationHandle> application =
4073 std::make_shared<FakeApplicationHandle>();
4074
4075 // Add two windows to the display. Their frames are represented in the display space.
4076 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004077 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4078 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004079 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4080 addWindow(firstWindow);
4081
4082 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004083 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4084 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004085 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4086 addWindow(secondWindow);
4087 return {std::move(firstWindow), std::move(secondWindow)};
4088 }
4089
4090private:
4091 std::vector<gui::DisplayInfo> mDisplayInfos;
4092 std::vector<gui::WindowInfo> mWindowInfos;
4093};
4094
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004095TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004096 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4097 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004098 // selected so that if the hit test was performed with the point and the bounds being in
4099 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004100 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4101 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4102 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004103
4104 firstWindow->consumeMotionDown();
4105 secondWindow->assertNoEvents();
4106}
4107
4108// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4109// the event should be treated as being in the logical display space.
4110TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4111 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4112 // Send down to the first window. The point is represented in the logical display space. The
4113 // point is selected so that if the hit test was done in logical display space, then it would
4114 // end up in the incorrect window.
4115 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4116 PointF{75 * 2, 55 * 4});
4117
4118 firstWindow->consumeMotionDown();
4119 secondWindow->assertNoEvents();
4120}
4121
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004122// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4123// event should be treated as being in the logical display space.
4124TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4125 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4126
4127 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4128 ui::Transform injectedEventTransform;
4129 injectedEventTransform.set(matrix);
4130 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4131 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4132
4133 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4134 .displayId(ADISPLAY_ID_DEFAULT)
4135 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004136 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004137 .x(untransformedPoint.x)
4138 .y(untransformedPoint.y))
4139 .build();
4140 event.transform(matrix);
4141
4142 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4143 InputEventInjectionSync::WAIT_FOR_RESULT);
4144
4145 firstWindow->consumeMotionDown();
4146 secondWindow->assertNoEvents();
4147}
4148
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004149TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4150 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4151
4152 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004153 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4154 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4155 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004156
4157 firstWindow->assertNoEvents();
4158 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004159 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004160 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4161
4162 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4163 EXPECT_EQ(300, event->getRawX(0));
4164 EXPECT_EQ(880, event->getRawY(0));
4165
4166 // Ensure that the x and y values are in the window's coordinate space.
4167 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4168 // the logical display space. This will be the origin of the window space.
4169 EXPECT_EQ(100, event->getX(0));
4170 EXPECT_EQ(80, event->getY(0));
4171}
4172
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004173/** Ensure consistent behavior of InputDispatcher in all orientations. */
4174class InputDispatcherDisplayOrientationFixture
4175 : public InputDispatcherDisplayProjectionTest,
4176 public ::testing::WithParamInterface<ui::Rotation> {};
4177
4178// This test verifies the touchable region of a window for all rotations of the display by tapping
4179// in different locations on the display, specifically points close to the four corners of a
4180// window.
4181TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4182 constexpr static int32_t displayWidth = 400;
4183 constexpr static int32_t displayHeight = 800;
4184
4185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4186
4187 const auto rotation = GetParam();
4188
4189 // Set up the display with the specified rotation.
4190 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4191 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4192 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4193 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4194 logicalDisplayWidth, logicalDisplayHeight);
4195 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4196
4197 // Create a window with its bounds determined in the logical display.
4198 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4199 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4200 sp<FakeWindowHandle> window =
4201 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4202 window->setFrame(frameInDisplay, displayTransform);
4203 addWindow(window);
4204
4205 // The following points in logical display space should be inside the window.
4206 static const std::array<vec2, 4> insidePoints{
4207 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4208 for (const auto pointInsideWindow : insidePoints) {
4209 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4210 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004211 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4212 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4213 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004214 window->consumeMotionDown();
4215
Prabir Pradhan678438e2023-04-13 19:32:51 +00004216 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4217 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4218 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004219 window->consumeMotionUp();
4220 }
4221
4222 // The following points in logical display space should be outside the window.
4223 static const std::array<vec2, 5> outsidePoints{
4224 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4225 for (const auto pointOutsideWindow : outsidePoints) {
4226 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4227 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004228 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4229 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4230 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004231
Prabir Pradhan678438e2023-04-13 19:32:51 +00004232 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4233 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4234 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004235 }
4236 window->assertNoEvents();
4237}
4238
4239// Run the precision tests for all rotations.
4240INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4241 InputDispatcherDisplayOrientationFixture,
4242 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4243 ui::ROTATION_270),
4244 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4245 return ftl::enum_string(testParamInfo.param);
4246 });
4247
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004248using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4249 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004250
4251class TransferTouchFixture : public InputDispatcherTest,
4252 public ::testing::WithParamInterface<TransferFunction> {};
4253
4254TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004256
4257 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004258 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004259 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4260 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004261 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004262 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004263 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4264 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004265 sp<FakeWindowHandle> wallpaper =
4266 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4267 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004268 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004269 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004270
4271 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004272 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4273 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004274
Svet Ganov5d3bc372020-01-26 23:11:07 -08004275 // Only the first window should get the down event
4276 firstWindow->consumeMotionDown();
4277 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004278 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004279
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004280 // Transfer touch to the second window
4281 TransferFunction f = GetParam();
4282 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4283 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004284 // The first window gets cancel and the second gets down
4285 firstWindow->consumeMotionCancel();
4286 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004287 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004288
4289 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004290 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4291 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004292 // The first window gets no events and the second gets up
4293 firstWindow->assertNoEvents();
4294 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004295 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004296}
4297
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004298/**
4299 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4300 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4301 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4302 * natural to the user.
4303 * In this test, we are sending a pointer to both spy window and first window. We then try to
4304 * transfer touch to the second window. The dispatcher should identify the first window as the
4305 * one that should lose the gesture, and therefore the action should be to move the gesture from
4306 * the first window to the second.
4307 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4308 * the other API, as well.
4309 */
4310TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4311 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4312
4313 // Create a couple of windows + a spy window
4314 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004315 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004316 spyWindow->setTrustedOverlay(true);
4317 spyWindow->setSpy(true);
4318 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004319 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004320 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004321 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004322
4323 // Add the windows to the dispatcher
4324 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4325
4326 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004327 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4328 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004329 // Only the first window and spy should get the down event
4330 spyWindow->consumeMotionDown();
4331 firstWindow->consumeMotionDown();
4332
4333 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4334 // if f === 'transferTouch'.
4335 TransferFunction f = GetParam();
4336 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4337 ASSERT_TRUE(success);
4338 // The first window gets cancel and the second gets down
4339 firstWindow->consumeMotionCancel();
4340 secondWindow->consumeMotionDown();
4341
4342 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004343 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4344 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004345 // The first window gets no events and the second+spy get up
4346 firstWindow->assertNoEvents();
4347 spyWindow->consumeMotionUp();
4348 secondWindow->consumeMotionUp();
4349}
4350
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004351TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004353
4354 PointF touchPoint = {10, 10};
4355
4356 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004357 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004358 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4359 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004360 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004361 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004362 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4363 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004364 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004365
4366 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004367 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004368
4369 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004370 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4371 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4372 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004373 // Only the first window should get the down event
4374 firstWindow->consumeMotionDown();
4375 secondWindow->assertNoEvents();
4376
4377 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004378 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4379 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004380 // Only the first window should get the pointer down event
4381 firstWindow->consumeMotionPointerDown(1);
4382 secondWindow->assertNoEvents();
4383
4384 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004385 TransferFunction f = GetParam();
4386 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4387 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004388 // The first window gets cancel and the second gets down and pointer down
4389 firstWindow->consumeMotionCancel();
4390 secondWindow->consumeMotionDown();
4391 secondWindow->consumeMotionPointerDown(1);
4392
4393 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004394 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4395 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004396 // The first window gets nothing and the second gets pointer up
4397 firstWindow->assertNoEvents();
4398 secondWindow->consumeMotionPointerUp(1);
4399
4400 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004401 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4402 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004403 // The first window gets nothing and the second gets up
4404 firstWindow->assertNoEvents();
4405 secondWindow->consumeMotionUp();
4406}
4407
Arthur Hungc539dbb2022-12-08 07:45:36 +00004408TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4410
4411 // Create a couple of windows
4412 sp<FakeWindowHandle> firstWindow =
4413 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4414 ADISPLAY_ID_DEFAULT);
4415 firstWindow->setDupTouchToWallpaper(true);
4416 sp<FakeWindowHandle> secondWindow =
4417 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4418 ADISPLAY_ID_DEFAULT);
4419 secondWindow->setDupTouchToWallpaper(true);
4420
4421 sp<FakeWindowHandle> wallpaper1 =
4422 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4423 wallpaper1->setIsWallpaper(true);
4424
4425 sp<FakeWindowHandle> wallpaper2 =
4426 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4427 wallpaper2->setIsWallpaper(true);
4428 // Add the windows to the dispatcher
4429 mDispatcher->setInputWindows(
4430 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4431
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
Arthur Hung72d8dc32020-03-28 00:48:39 +00004493 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004494
4495 PointF pointInFirst = {300, 200};
4496 PointF pointInSecond = {300, 600};
4497
4498 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004499 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4500 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4501 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004502 // Only the first window should get the down event
4503 firstWindow->consumeMotionDown();
4504 secondWindow->assertNoEvents();
4505
4506 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004507 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4508 ADISPLAY_ID_DEFAULT,
4509 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004510 // The first window gets a move and the second a down
4511 firstWindow->consumeMotionMove();
4512 secondWindow->consumeMotionDown();
4513
4514 // Transfer touch focus to the second window
4515 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4516 // The first window gets cancel and the new gets pointer down (it already saw down)
4517 firstWindow->consumeMotionCancel();
4518 secondWindow->consumeMotionPointerDown(1);
4519
4520 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004521 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4522 ADISPLAY_ID_DEFAULT,
4523 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004524 // The first window gets nothing and the second gets pointer up
4525 firstWindow->assertNoEvents();
4526 secondWindow->consumeMotionPointerUp(1);
4527
4528 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004529 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4530 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004531 // The first window gets nothing and the second gets up
4532 firstWindow->assertNoEvents();
4533 secondWindow->consumeMotionUp();
4534}
4535
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004536// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4537// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4538// touch is not supported, so the touch should continue on those windows and the transferred-to
4539// window should get nothing.
4540TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4542
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004543 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004544 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4545 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004546 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004547
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004548 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004549 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4550 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004551 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004552
4553 // Add the windows to the dispatcher
4554 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4555
4556 PointF pointInFirst = {300, 200};
4557 PointF pointInSecond = {300, 600};
4558
4559 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004560 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4561 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4562 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004563 // Only the first window should get the down event
4564 firstWindow->consumeMotionDown();
4565 secondWindow->assertNoEvents();
4566
4567 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004568 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4569 ADISPLAY_ID_DEFAULT,
4570 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004571 // The first window gets a move and the second a down
4572 firstWindow->consumeMotionMove();
4573 secondWindow->consumeMotionDown();
4574
4575 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004576 const bool transferred =
4577 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004578 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4579 ASSERT_FALSE(transferred);
4580 firstWindow->assertNoEvents();
4581 secondWindow->assertNoEvents();
4582
4583 // The rest of the dispatch should proceed as normal
4584 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004585 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4586 ADISPLAY_ID_DEFAULT,
4587 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004588 // The first window gets MOVE and the second gets pointer up
4589 firstWindow->consumeMotionMove();
4590 secondWindow->consumeMotionUp();
4591
4592 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004593 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4594 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004595 // The first window gets nothing and the second gets up
4596 firstWindow->consumeMotionUp();
4597 secondWindow->assertNoEvents();
4598}
4599
Arthur Hungabbb9d82021-09-01 14:52:30 +00004600// This case will create two windows and one mirrored window on the default display and mirror
4601// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4602// the windows info of second display before default display.
4603TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4605 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004606 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004607 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004608 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004609 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004610 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004611
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004612 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004613 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004614
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004615 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004616 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004617
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004618 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004619 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004620
4621 // Update window info, let it find window handle of second display first.
4622 mDispatcher->setInputWindows(
4623 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4624 {ADISPLAY_ID_DEFAULT,
4625 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4626
4627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4628 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4629 {50, 50}))
4630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4631
4632 // Window should receive motion event.
4633 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4634
4635 // Transfer touch focus
4636 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4637 secondWindowInPrimary->getToken()));
4638 // The first window gets cancel.
4639 firstWindowInPrimary->consumeMotionCancel();
4640 secondWindowInPrimary->consumeMotionDown();
4641
4642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4643 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4644 ADISPLAY_ID_DEFAULT, {150, 50}))
4645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4646 firstWindowInPrimary->assertNoEvents();
4647 secondWindowInPrimary->consumeMotionMove();
4648
4649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4650 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4651 {150, 50}))
4652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4653 firstWindowInPrimary->assertNoEvents();
4654 secondWindowInPrimary->consumeMotionUp();
4655}
4656
4657// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4658// 'transferTouch' api.
4659TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4661 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004662 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004663 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004664 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004665 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004666 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004667
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004668 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004669 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004670
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004671 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004672 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004673
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004674 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004675 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004676
4677 // Update window info, let it find window handle of second display first.
4678 mDispatcher->setInputWindows(
4679 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4680 {ADISPLAY_ID_DEFAULT,
4681 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4682
4683 // Touch on second display.
4684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4685 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4687
4688 // Window should receive motion event.
4689 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4690
4691 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004692 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004693
4694 // The first window gets cancel.
4695 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4696 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4697
4698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4699 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4700 SECOND_DISPLAY_ID, {150, 50}))
4701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4702 firstWindowInPrimary->assertNoEvents();
4703 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4704
4705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4706 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4708 firstWindowInPrimary->assertNoEvents();
4709 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4710}
4711
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004712TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4715 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004716
Vishnu Nair47074b82020-08-14 11:54:47 -07004717 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004718 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004719 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004720
4721 window->consumeFocusEvent(true);
4722
Prabir Pradhan678438e2023-04-13 19:32:51 +00004723 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004724
4725 // Window should receive key down event.
4726 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004727
4728 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004729 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004730 mFakePolicy->assertUserActivityPoked();
4731}
4732
4733TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4734 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4735 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4736 "Fake Window", ADISPLAY_ID_DEFAULT);
4737
4738 window->setDisableUserActivity(true);
4739 window->setFocusable(true);
4740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4741 setFocusedWindow(window);
4742
4743 window->consumeFocusEvent(true);
4744
4745 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4746
4747 // Window should receive key down event.
4748 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4749
4750 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004751 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004752 mFakePolicy->assertUserActivityNotPoked();
4753}
4754
4755TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4758 "Fake Window", ADISPLAY_ID_DEFAULT);
4759
4760 window->setFocusable(true);
4761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4762 setFocusedWindow(window);
4763
4764 window->consumeFocusEvent(true);
4765
4766 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4767 mDispatcher->waitForIdle();
4768
4769 // System key is not passed down
4770 window->assertNoEvents();
4771
4772 // Should have poked user activity
4773 mFakePolicy->assertUserActivityPoked();
4774}
4775
4776TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4778 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4779 "Fake Window", ADISPLAY_ID_DEFAULT);
4780
4781 window->setFocusable(true);
4782 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4783 setFocusedWindow(window);
4784
4785 window->consumeFocusEvent(true);
4786
4787 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4788 mDispatcher->waitForIdle();
4789
4790 // System key is not passed down
4791 window->assertNoEvents();
4792
4793 // Should have poked user activity
4794 mFakePolicy->assertUserActivityPoked();
4795}
4796
4797TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4799 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4800 "Fake Window", ADISPLAY_ID_DEFAULT);
4801
4802 window->setDisableUserActivity(true);
4803 window->setFocusable(true);
4804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4805 setFocusedWindow(window);
4806
4807 window->consumeFocusEvent(true);
4808
4809 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4810 mDispatcher->waitForIdle();
4811
4812 // System key is not passed down
4813 window->assertNoEvents();
4814
4815 // Should have poked user activity
4816 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004817}
4818
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004819TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4821 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4822 "Fake Window", ADISPLAY_ID_DEFAULT);
4823
4824 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4825
4826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4827 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4828 ADISPLAY_ID_DEFAULT, {100, 100}))
4829 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4830
4831 window->consumeMotionEvent(
4832 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4833
4834 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004835 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004836 mFakePolicy->assertUserActivityPoked();
4837}
4838
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004839TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004841 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4842 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004843
Arthur Hung72d8dc32020-03-28 00:48:39 +00004844 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004845
Prabir Pradhan678438e2023-04-13 19:32:51 +00004846 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004847 mDispatcher->waitForIdle();
4848
4849 window->assertNoEvents();
4850}
4851
4852// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4853TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004855 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4856 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004857
Arthur Hung72d8dc32020-03-28 00:48:39 +00004858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004859
4860 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004861 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004862 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004863 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4864 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004865
4866 // Window should receive only the motion event
4867 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4868 window->assertNoEvents(); // Key event or focus event will not be received
4869}
4870
arthurhungea3f4fc2020-12-21 23:18:53 +08004871TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4873
arthurhungea3f4fc2020-12-21 23:18:53 +08004874 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004875 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4876 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004877 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004878
arthurhungea3f4fc2020-12-21 23:18:53 +08004879 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004880 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4881 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004882 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004883
4884 // Add the windows to the dispatcher
4885 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4886
4887 PointF pointInFirst = {300, 200};
4888 PointF pointInSecond = {300, 600};
4889
4890 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004891 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4892 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4893 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004894 // Only the first window should get the down event
4895 firstWindow->consumeMotionDown();
4896 secondWindow->assertNoEvents();
4897
4898 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004899 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4900 ADISPLAY_ID_DEFAULT,
4901 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004902 // The first window gets a move and the second a down
4903 firstWindow->consumeMotionMove();
4904 secondWindow->consumeMotionDown();
4905
4906 // Send pointer cancel to the second window
4907 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004908 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004909 {pointInFirst, pointInSecond});
4910 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004911 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004912 // The first window gets move and the second gets cancel.
4913 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4914 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4915
4916 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004917 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4918 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004919 // The first window gets up and the second gets nothing.
4920 firstWindow->consumeMotionUp();
4921 secondWindow->assertNoEvents();
4922}
4923
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004924TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4926
4927 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004928 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4930 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4931 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4932 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4933
Harry Cutts33476232023-01-30 19:57:29 +00004934 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004935 window->assertNoEvents();
4936 mDispatcher->waitForIdle();
4937}
4938
chaviwd1c23182019-12-20 18:44:56 -08004939class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004940public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004941 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004942 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004943 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004944 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004945 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004946 }
4947
chaviwd1c23182019-12-20 18:44:56 -08004948 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4949
4950 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004951 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4952 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004953 }
4954
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004955 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4956
4957 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4958
chaviwd1c23182019-12-20 18:44:56 -08004959 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004960 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004961 expectedDisplayId, expectedFlags);
4962 }
4963
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004964 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004965 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004966 expectedDisplayId, expectedFlags);
4967 }
4968
chaviwd1c23182019-12-20 18:44:56 -08004969 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004970 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004971 expectedDisplayId, expectedFlags);
4972 }
4973
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004974 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004975 mInputReceiver->consumeMotionEvent(
4976 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4977 WithDisplayId(expectedDisplayId),
4978 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004979 }
4980
Arthur Hungfbfa5722021-11-16 02:45:54 +00004981 void consumeMotionPointerDown(int32_t pointerIdx) {
4982 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4983 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004984 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004985 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004986 }
4987
Evan Rosky84f07f02021-04-16 10:42:42 -07004988 MotionEvent* consumeMotion() {
4989 InputEvent* event = mInputReceiver->consume();
4990 if (!event) {
4991 ADD_FAILURE() << "No event was produced";
4992 return nullptr;
4993 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004994 if (event->getType() != InputEventType::MOTION) {
4995 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004996 return nullptr;
4997 }
4998 return static_cast<MotionEvent*>(event);
4999 }
5000
chaviwd1c23182019-12-20 18:44:56 -08005001 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5002
5003private:
5004 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005005};
5006
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005007using InputDispatcherMonitorTest = InputDispatcherTest;
5008
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005009/**
5010 * Two entities that receive touch: A window, and a global monitor.
5011 * The touch goes to the window, and then the window disappears.
5012 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5013 * for the monitor, as well.
5014 * 1. foregroundWindow
5015 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5016 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005017TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5019 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005020 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005021
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005022 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005023
5024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5026 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5027 {100, 200}))
5028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5029
5030 // Both the foreground window and the global monitor should receive the touch down
5031 window->consumeMotionDown();
5032 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5033
5034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5035 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5036 ADISPLAY_ID_DEFAULT, {110, 200}))
5037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5038
5039 window->consumeMotionMove();
5040 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5041
5042 // Now the foreground window goes away
5043 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5044 window->consumeMotionCancel();
5045 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5046
5047 // If more events come in, there will be no more foreground window to send them to. This will
5048 // cause a cancel for the monitor, as well.
5049 ASSERT_EQ(InputEventInjectionResult::FAILED,
5050 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5051 ADISPLAY_ID_DEFAULT, {120, 200}))
5052 << "Injection should fail because the window was removed";
5053 window->assertNoEvents();
5054 // Global monitor now gets the cancel
5055 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5056}
5057
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005058TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005059 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005060 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5061 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005063
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005064 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005065
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005067 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005069 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005070 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005071}
5072
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005073TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5074 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005075
Chris Yea209fde2020-07-22 13:54:51 -07005076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005077 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5078 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005079 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005080
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005082 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005084 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005085 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005086
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005087 // Pilfer pointers from the monitor.
5088 // This should not do anything and the window should continue to receive events.
5089 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005090
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005092 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5093 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005095
5096 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5097 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005098}
5099
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005100TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005102 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5103 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005104 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5105 window->setWindowOffset(20, 40);
5106 window->setWindowTransform(0, 1, -1, 0);
5107
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005108 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005109
5110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5111 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5113 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5114 MotionEvent* event = monitor.consumeMotion();
5115 // Even though window has transform, gesture monitor must not.
5116 ASSERT_EQ(ui::Transform(), event->getTransform());
5117}
5118
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005119TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005120 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005121 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005122
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005123 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005124 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005125 << "Injection should fail if there is a monitor, but no touchable window";
5126 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005127}
5128
chaviw81e2bb92019-12-18 15:03:51 -08005129TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005131 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5132 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005133
Arthur Hung72d8dc32020-03-28 00:48:39 +00005134 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005135
5136 NotifyMotionArgs motionArgs =
5137 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5138 ADISPLAY_ID_DEFAULT);
5139
Prabir Pradhan678438e2023-04-13 19:32:51 +00005140 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005141 // Window should receive motion down event.
5142 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5143
5144 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005145 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005146 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5147 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5148 motionArgs.pointerCoords[0].getX() - 10);
5149
Prabir Pradhan678438e2023-04-13 19:32:51 +00005150 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005151 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005152 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005153}
5154
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005155/**
5156 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5157 * the device default right away. In the test scenario, we check both the default value,
5158 * and the action of enabling / disabling.
5159 */
5160TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005162 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5163 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005164 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005165
5166 // Set focused application.
5167 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005168 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005169
5170 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005172 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005173 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005174
5175 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005176 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005177 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005178 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005179
5180 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005181 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005182 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005183 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005184 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005186 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005187 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005188
5189 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005190 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005191 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005192 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005193
5194 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005195 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005196 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005197 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005198 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005199 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005200 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005201 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005202
5203 window->assertNoEvents();
5204}
5205
Gang Wange9087892020-01-07 12:17:14 -05005206TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005208 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5209 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005210
5211 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005212 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005213
Arthur Hung72d8dc32020-03-28 00:48:39 +00005214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005215 setFocusedWindow(window);
5216
Harry Cutts33476232023-01-30 19:57:29 +00005217 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005218
Prabir Pradhan678438e2023-04-13 19:32:51 +00005219 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5220 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005221
5222 InputEvent* event = window->consume();
5223 ASSERT_NE(event, nullptr);
5224
5225 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5226 ASSERT_NE(verified, nullptr);
5227 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5228
5229 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5230 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5231 ASSERT_EQ(keyArgs.source, verified->source);
5232 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5233
5234 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5235
5236 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005237 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005238 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005239 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5240 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5241 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5242 ASSERT_EQ(0, verifiedKey.repeatCount);
5243}
5244
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005245TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005247 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5248 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005249
5250 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5251
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005252 ui::Transform transform;
5253 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5254
5255 gui::DisplayInfo displayInfo;
5256 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5257 displayInfo.transform = transform;
5258
Patrick Williamsd828f302023-04-28 17:52:08 -05005259 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005260
Prabir Pradhan678438e2023-04-13 19:32:51 +00005261 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005262 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5263 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005264 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005265
5266 InputEvent* event = window->consume();
5267 ASSERT_NE(event, nullptr);
5268
5269 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5270 ASSERT_NE(verified, nullptr);
5271 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5272
5273 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5274 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5275 EXPECT_EQ(motionArgs.source, verified->source);
5276 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5277
5278 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5279
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005280 const vec2 rawXY =
5281 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5282 motionArgs.pointerCoords[0].getXYValue());
5283 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5284 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005285 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005286 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005287 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005288 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5289 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5290}
5291
chaviw09c8d2d2020-08-24 15:48:26 -07005292/**
5293 * Ensure that separate calls to sign the same data are generating the same key.
5294 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5295 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5296 * tests.
5297 */
5298TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5299 KeyEvent event = getTestKeyEvent();
5300 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5301
5302 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5303 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5304 ASSERT_EQ(hmac1, hmac2);
5305}
5306
5307/**
5308 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5309 */
5310TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5311 KeyEvent event = getTestKeyEvent();
5312 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5313 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5314
5315 verifiedEvent.deviceId += 1;
5316 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5317
5318 verifiedEvent.source += 1;
5319 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5320
5321 verifiedEvent.eventTimeNanos += 1;
5322 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5323
5324 verifiedEvent.displayId += 1;
5325 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5326
5327 verifiedEvent.action += 1;
5328 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5329
5330 verifiedEvent.downTimeNanos += 1;
5331 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5332
5333 verifiedEvent.flags += 1;
5334 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5335
5336 verifiedEvent.keyCode += 1;
5337 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5338
5339 verifiedEvent.scanCode += 1;
5340 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5341
5342 verifiedEvent.metaState += 1;
5343 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5344
5345 verifiedEvent.repeatCount += 1;
5346 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5347}
5348
Vishnu Nair958da932020-08-21 17:12:37 -07005349TEST_F(InputDispatcherTest, SetFocusedWindow) {
5350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5351 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005352 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005353 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005354 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005355 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5356
5357 // Top window is also focusable but is not granted focus.
5358 windowTop->setFocusable(true);
5359 windowSecond->setFocusable(true);
5360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5361 setFocusedWindow(windowSecond);
5362
5363 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5365 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005366
5367 // Focused window should receive event.
5368 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5369 windowTop->assertNoEvents();
5370}
5371
5372TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5373 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5374 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005375 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005376 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5377
5378 window->setFocusable(true);
5379 // Release channel for window is no longer valid.
5380 window->releaseChannel();
5381 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5382 setFocusedWindow(window);
5383
5384 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005385 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5386 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005387
5388 // window channel is invalid, so it should not receive any input event.
5389 window->assertNoEvents();
5390}
5391
5392TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5394 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005395 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005396 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005397 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5398
Vishnu Nair958da932020-08-21 17:12:37 -07005399 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5400 setFocusedWindow(window);
5401
5402 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005403 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5404 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005405
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005406 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005407 window->assertNoEvents();
5408}
5409
5410TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5412 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005413 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005414 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005415 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005416 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5417
5418 windowTop->setFocusable(true);
5419 windowSecond->setFocusable(true);
5420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5421 setFocusedWindow(windowTop);
5422 windowTop->consumeFocusEvent(true);
5423
Chavi Weingarten847e8512023-03-29 00:26:09 +00005424 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5425 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005426 windowSecond->consumeFocusEvent(true);
5427 windowTop->consumeFocusEvent(false);
5428
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5430 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005431
5432 // Focused window should receive event.
5433 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5434}
5435
Chavi Weingarten847e8512023-03-29 00:26:09 +00005436TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005437 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5438 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005439 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005440 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005441 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005442 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5443
5444 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005445 windowSecond->setFocusable(false);
5446 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005448 setFocusedWindow(windowTop);
5449 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005450
Chavi Weingarten847e8512023-03-29 00:26:09 +00005451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5452 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005453
5454 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005455 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005456 windowSecond->assertNoEvents();
5457}
5458
5459TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5461 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005462 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005463 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005464 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5465 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005466 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5467
5468 window->setFocusable(true);
5469 previousFocusedWindow->setFocusable(true);
5470 window->setVisible(false);
5471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5472 setFocusedWindow(previousFocusedWindow);
5473 previousFocusedWindow->consumeFocusEvent(true);
5474
5475 // Requesting focus on invisible window takes focus from currently focused window.
5476 setFocusedWindow(window);
5477 previousFocusedWindow->consumeFocusEvent(false);
5478
5479 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005481 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5482 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005483
5484 // Window does not get focus event or key down.
5485 window->assertNoEvents();
5486
5487 // Window becomes visible.
5488 window->setVisible(true);
5489 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5490
5491 // Window receives focus event.
5492 window->consumeFocusEvent(true);
5493 // Focused window receives key down.
5494 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5495}
5496
Vishnu Nair599f1412021-06-21 10:39:58 -07005497TEST_F(InputDispatcherTest, DisplayRemoved) {
5498 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5499 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005500 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005501 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5502
5503 // window is granted focus.
5504 window->setFocusable(true);
5505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5506 setFocusedWindow(window);
5507 window->consumeFocusEvent(true);
5508
5509 // When a display is removed window loses focus.
5510 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5511 window->consumeFocusEvent(false);
5512}
5513
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005514/**
5515 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5516 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5517 * of the 'slipperyEnterWindow'.
5518 *
5519 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5520 * a way so that the touched location is no longer covered by the top window.
5521 *
5522 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5523 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5524 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5525 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5526 * with ACTION_DOWN).
5527 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5528 * window moved itself away from the touched location and had Flag::SLIPPERY.
5529 *
5530 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5531 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5532 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5533 *
5534 * In this test, we ensure that the event received by the bottom window has
5535 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5536 */
5537TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005538 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005539 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005540
5541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5542 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5543
5544 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005545 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005546 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005547 // Make sure this one overlaps the bottom window
5548 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5549 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5550 // one. Windows with the same owner are not considered to be occluding each other.
5551 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5552
5553 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005554 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005555 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5556
5557 mDispatcher->setInputWindows(
5558 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5559
5560 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005561 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5562 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5563 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005564 slipperyExitWindow->consumeMotionDown();
5565 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5566 mDispatcher->setInputWindows(
5567 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5568
Prabir Pradhan678438e2023-04-13 19:32:51 +00005569 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5570 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5571 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005572
5573 slipperyExitWindow->consumeMotionCancel();
5574
5575 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5576 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5577}
5578
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005579/**
5580 * Two windows, one on the left and another on the right. The left window is slippery. The right
5581 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5582 * touch moves from the left window into the right window, the gesture should continue to go to the
5583 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5584 * reproduces a crash.
5585 */
5586TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5587 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5588
5589 sp<FakeWindowHandle> leftSlipperyWindow =
5590 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5591 leftSlipperyWindow->setSlippery(true);
5592 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5593
5594 sp<FakeWindowHandle> rightDropTouchesWindow =
5595 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5596 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5597 rightDropTouchesWindow->setDropInput(true);
5598
5599 mDispatcher->setInputWindows(
5600 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5601
5602 // Start touch in the left window
5603 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5604 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5605 .build());
5606 leftSlipperyWindow->consumeMotionDown();
5607
5608 // And move it into the right window
5609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5610 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5611 .build());
5612
5613 // Since the right window isn't eligible to receive input, touch does not slip.
5614 // The left window continues to receive the gesture.
5615 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5616 rightDropTouchesWindow->assertNoEvents();
5617}
5618
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005619TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005620 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005621 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5622
5623 sp<FakeWindowHandle> leftWindow =
5624 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5625 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005626 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005627
5628 sp<FakeWindowHandle> rightSpy =
5629 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5630 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005631 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005632 rightSpy->setSpy(true);
5633 rightSpy->setTrustedOverlay(true);
5634
5635 sp<FakeWindowHandle> rightWindow =
5636 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5637 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005638 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005639
5640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5641
5642 // Touch in the left window
5643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5645 .build());
5646 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5647 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005648 ASSERT_NO_FATAL_FAILURE(
5649 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005650
5651 // Touch another finger over the right windows
5652 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5653 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5654 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5655 .build());
5656 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5657 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5658 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5659 mDispatcher->waitForIdle();
5660 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005661 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5662 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005663
5664 // Release finger over left window. The UP actions are not treated as device interaction.
5665 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5666 // is part of the UP action, we do not treat this as device interaction.
5667 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, 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(leftWindow->consumeMotionUp());
5672 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5673 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5674 mDispatcher->waitForIdle();
5675 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5676
5677 // Move remaining finger
5678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5679 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5680 .build());
5681 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5682 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5683 mDispatcher->waitForIdle();
5684 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005685 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005686
5687 // Release all fingers
5688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5689 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5690 .build());
5691 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5692 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5693 mDispatcher->waitForIdle();
5694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5695}
5696
5697TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5699
5700 sp<FakeWindowHandle> window =
5701 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5702 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005703 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005704
5705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5706 setFocusedWindow(window);
5707 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5708
5709 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5710 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5711 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005712 ASSERT_NO_FATAL_FAILURE(
5713 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005714
5715 // The UP actions are not treated as device interaction.
5716 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5717 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5718 mDispatcher->waitForIdle();
5719 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5720}
5721
Garfield Tan1c7bc862020-01-28 13:24:04 -08005722class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5723protected:
5724 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5725 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5726
Chris Yea209fde2020-07-22 13:54:51 -07005727 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005728 sp<FakeWindowHandle> mWindow;
5729
5730 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005731 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005732 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005733 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005734 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005735 ASSERT_EQ(OK, mDispatcher->start());
5736
5737 setUpWindow();
5738 }
5739
5740 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005741 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005742 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005743
Vishnu Nair47074b82020-08-14 11:54:47 -07005744 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005745 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005746 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005747 mWindow->consumeFocusEvent(true);
5748 }
5749
Chris Ye2ad95392020-09-01 13:44:44 -07005750 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005751 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005752 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005753 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005754 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005755
5756 // Window should receive key down event.
5757 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5758 }
5759
5760 void expectKeyRepeatOnce(int32_t repeatCount) {
5761 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5762 InputEvent* repeatEvent = mWindow->consume();
5763 ASSERT_NE(nullptr, repeatEvent);
5764
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005765 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005766
5767 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5768 uint32_t eventAction = repeatKeyEvent->getAction();
5769 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5770 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5771 }
5772
Chris Ye2ad95392020-09-01 13:44:44 -07005773 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005774 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005775 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005776 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005777 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005778
5779 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005780 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005781 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005782 }
5783};
5784
5785TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005786 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005787 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5788 expectKeyRepeatOnce(repeatCount);
5789 }
5790}
5791
5792TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005793 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005794 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5795 expectKeyRepeatOnce(repeatCount);
5796 }
Harry Cutts33476232023-01-30 19:57:29 +00005797 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005798 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005799 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5800 expectKeyRepeatOnce(repeatCount);
5801 }
5802}
5803
5804TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005805 sendAndConsumeKeyDown(/*deviceId=*/1);
5806 expectKeyRepeatOnce(/*repeatCount=*/1);
5807 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005808 mWindow->assertNoEvents();
5809}
5810
5811TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005812 sendAndConsumeKeyDown(/*deviceId=*/1);
5813 expectKeyRepeatOnce(/*repeatCount=*/1);
5814 sendAndConsumeKeyDown(/*deviceId=*/2);
5815 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005816 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005817 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005818 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005819 expectKeyRepeatOnce(/*repeatCount=*/2);
5820 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005821 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005822 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005823 mWindow->assertNoEvents();
5824}
5825
5826TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
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 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005832 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005833 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005834 mWindow->assertNoEvents();
5835}
5836
liushenxiang42232912021-05-21 20:24:09 +08005837TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5838 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005839 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005840 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005841 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5842 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5843 mWindow->assertNoEvents();
5844}
5845
Garfield Tan1c7bc862020-01-28 13:24:04 -08005846TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005847 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005848 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005849 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5850 InputEvent* repeatEvent = mWindow->consume();
5851 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5852 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5853 IdGenerator::getSource(repeatEvent->getId()));
5854 }
5855}
5856
5857TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005858 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005859 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005860
5861 std::unordered_set<int32_t> idSet;
5862 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5863 InputEvent* repeatEvent = mWindow->consume();
5864 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5865 int32_t id = repeatEvent->getId();
5866 EXPECT_EQ(idSet.end(), idSet.find(id));
5867 idSet.insert(id);
5868 }
5869}
5870
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005871/* Test InputDispatcher for MultiDisplay */
5872class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5873public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005874 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005876
Chris Yea209fde2020-07-22 13:54:51 -07005877 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005878 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005879 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005880
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005881 // Set focus window for primary display, but focused display would be second one.
5882 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005883 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005885 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005886 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005887
Chris Yea209fde2020-07-22 13:54:51 -07005888 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005889 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005890 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005891 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005892 // Set focus display to second one.
5893 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5894 // Set focus window for second display.
5895 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005896 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005897 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005898 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005899 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005900 }
5901
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005902 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005903 InputDispatcherTest::TearDown();
5904
Chris Yea209fde2020-07-22 13:54:51 -07005905 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005906 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005907 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005908 windowInSecondary.clear();
5909 }
5910
5911protected:
Chris Yea209fde2020-07-22 13:54:51 -07005912 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005913 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005914 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005915 sp<FakeWindowHandle> windowInSecondary;
5916};
5917
5918TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5919 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5921 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005923 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005924 windowInSecondary->assertNoEvents();
5925
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005926 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5928 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005930 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005931 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005932}
5933
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005934TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005935 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5937 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005938 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005939 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005940 windowInSecondary->assertNoEvents();
5941
5942 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005944 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005945 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005946 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005947
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005948 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005949 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005950
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005951 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005952 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005953 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005954
5955 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005956 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005957 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005958 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005959 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005960 windowInSecondary->assertNoEvents();
5961}
5962
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005963// Test per-display input monitors for motion event.
5964TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005965 FakeMonitorReceiver monitorInPrimary =
5966 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5967 FakeMonitorReceiver monitorInSecondary =
5968 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005969
5970 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5972 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005974 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005975 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005976 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005977 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005978
5979 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5981 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5982 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005983 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005984 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005985 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005986 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005987
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005988 // Lift up the touch from the second display
5989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5990 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5992 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5993 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5994
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005995 // Test inject a non-pointer motion event.
5996 // If specific a display, it will dispatch to the focused window of particular display,
5997 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
6000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006001 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006002 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006003 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006004 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006005}
6006
6007// Test per-display input monitors for key event.
6008TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006009 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006010 FakeMonitorReceiver monitorInPrimary =
6011 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6012 FakeMonitorReceiver monitorInSecondary =
6013 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006014
6015 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6017 << "Inject key 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->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006021 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006022}
6023
Vishnu Nair958da932020-08-21 17:12:37 -07006024TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6025 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006026 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006027 secondWindowInPrimary->setFocusable(true);
6028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
6029 setFocusedWindow(secondWindowInPrimary);
6030 windowInPrimary->consumeFocusEvent(false);
6031 secondWindowInPrimary->consumeFocusEvent(true);
6032
6033 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6035 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006036 windowInPrimary->assertNoEvents();
6037 windowInSecondary->assertNoEvents();
6038 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6039}
6040
Arthur Hungdfd528e2021-12-08 13:23:04 +00006041TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6042 FakeMonitorReceiver monitorInPrimary =
6043 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6044 FakeMonitorReceiver monitorInSecondary =
6045 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6046
6047 // Test touch down on primary display.
6048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6051 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6052 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6053
6054 // Test touch down on second display.
6055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6056 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6058 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6059 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6060
6061 // Trigger cancel touch.
6062 mDispatcher->cancelCurrentTouch();
6063 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6064 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6065 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6066 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6067
6068 // Test inject a move motion event, no window/monitor should receive the event.
6069 ASSERT_EQ(InputEventInjectionResult::FAILED,
6070 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6071 ADISPLAY_ID_DEFAULT, {110, 200}))
6072 << "Inject motion event should return InputEventInjectionResult::FAILED";
6073 windowInPrimary->assertNoEvents();
6074 monitorInPrimary.assertNoEvents();
6075
6076 ASSERT_EQ(InputEventInjectionResult::FAILED,
6077 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6078 SECOND_DISPLAY_ID, {110, 200}))
6079 << "Inject motion event should return InputEventInjectionResult::FAILED";
6080 windowInSecondary->assertNoEvents();
6081 monitorInSecondary.assertNoEvents();
6082}
6083
Jackal Guof9696682018-10-05 12:23:23 +08006084class InputFilterTest : public InputDispatcherTest {
6085protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006086 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6087 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006088 NotifyMotionArgs motionArgs;
6089
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006090 motionArgs =
6091 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006092 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006093 motionArgs =
6094 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006095 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006096 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006097 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006098 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006099 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006100 } else {
6101 mFakePolicy->assertFilterInputEventWasNotCalled();
6102 }
6103 }
6104
6105 void testNotifyKey(bool expectToBeFiltered) {
6106 NotifyKeyArgs keyArgs;
6107
6108 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006109 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006110 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006111 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006112 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006113
6114 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006115 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006116 } else {
6117 mFakePolicy->assertFilterInputEventWasNotCalled();
6118 }
6119 }
6120};
6121
6122// Test InputFilter for MotionEvent
6123TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6124 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006125 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6126 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006127
6128 // Enable InputFilter
6129 mDispatcher->setInputFilterEnabled(true);
6130 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006131 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6132 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006133
6134 // Disable InputFilter
6135 mDispatcher->setInputFilterEnabled(false);
6136 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006137 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6138 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006139}
6140
6141// Test InputFilter for KeyEvent
6142TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6143 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006144 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006145
6146 // Enable InputFilter
6147 mDispatcher->setInputFilterEnabled(true);
6148 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006149 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006150
6151 // Disable InputFilter
6152 mDispatcher->setInputFilterEnabled(false);
6153 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006154 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006155}
6156
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006157// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6158// logical display coordinate space.
6159TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6160 ui::Transform firstDisplayTransform;
6161 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6162 ui::Transform secondDisplayTransform;
6163 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6164
6165 std::vector<gui::DisplayInfo> displayInfos(2);
6166 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6167 displayInfos[0].transform = firstDisplayTransform;
6168 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6169 displayInfos[1].transform = secondDisplayTransform;
6170
Patrick Williamsd828f302023-04-28 17:52:08 -05006171 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006172
6173 // Enable InputFilter
6174 mDispatcher->setInputFilterEnabled(true);
6175
6176 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006177 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6178 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006179}
6180
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006181class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6182protected:
6183 virtual void SetUp() override {
6184 InputDispatcherTest::SetUp();
6185
6186 /**
6187 * We don't need to enable input filter to test the injected event policy, but we enabled it
6188 * here to make the tests more realistic, since this policy only matters when inputfilter is
6189 * on.
6190 */
6191 mDispatcher->setInputFilterEnabled(true);
6192
6193 std::shared_ptr<InputApplicationHandle> application =
6194 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006195 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6196 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006197
6198 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6199 mWindow->setFocusable(true);
6200 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6201 setFocusedWindow(mWindow);
6202 mWindow->consumeFocusEvent(true);
6203 }
6204
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006205 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6206 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006207 KeyEvent event;
6208
6209 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6210 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6211 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006212 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006213 const int32_t additionalPolicyFlags =
6214 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006216 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006217 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006218 policyFlags | additionalPolicyFlags));
6219
6220 InputEvent* received = mWindow->consume();
6221 ASSERT_NE(nullptr, received);
6222 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006223 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006224 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6225 ASSERT_EQ(flags, keyEvent.getFlags());
6226 }
6227
6228 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6229 int32_t flags) {
6230 MotionEvent event;
6231 PointerProperties pointerProperties[1];
6232 PointerCoords pointerCoords[1];
6233 pointerProperties[0].clear();
6234 pointerProperties[0].id = 0;
6235 pointerCoords[0].clear();
6236 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6237 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6238
6239 ui::Transform identityTransform;
6240 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6241 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6242 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6243 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6244 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006245 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006246 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006247 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006248
6249 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006251 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006252 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006253 policyFlags | additionalPolicyFlags));
6254
6255 InputEvent* received = mWindow->consume();
6256 ASSERT_NE(nullptr, received);
6257 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006258 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006259 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6260 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006261 }
6262
6263private:
6264 sp<FakeWindowHandle> mWindow;
6265};
6266
6267TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006268 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6269 // filter. Without it, the event will no different from a regularly injected event, and the
6270 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006271 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6272 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006273}
6274
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006275TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006276 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006277 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006278 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6279}
6280
6281TEST_F(InputFilterInjectionPolicyTest,
6282 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6283 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006284 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006285 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006286}
6287
6288TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006289 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6290 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006291}
6292
chaviwfd6d3512019-03-25 13:23:49 -07006293class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006294 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006295 InputDispatcherTest::SetUp();
6296
Chris Yea209fde2020-07-22 13:54:51 -07006297 std::shared_ptr<FakeApplicationHandle> application =
6298 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006299 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006300 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006301 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006302
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006303 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006304 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006305 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006306
6307 // Set focused application.
6308 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006309 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006310
6311 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006312 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006313 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006314 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006315 }
6316
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006317 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006318 InputDispatcherTest::TearDown();
6319
6320 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006321 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006322 }
6323
6324protected:
6325 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006326 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006327 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006328};
6329
6330// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6331// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6332// the onPointerDownOutsideFocus callback.
6333TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006335 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6336 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006337 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006338 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006339
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006340 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006341 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6342}
6343
6344// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6345// DOWN on the window that doesn't have focus. Ensure no window received the
6346// onPointerDownOutsideFocus callback.
6347TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006349 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006350 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006351 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006352
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006353 ASSERT_TRUE(mDispatcher->waitForIdle());
6354 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006355}
6356
6357// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6358// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6359TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6361 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006362 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006363 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006364
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006365 ASSERT_TRUE(mDispatcher->waitForIdle());
6366 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006367}
6368
6369// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6370// DOWN on the window that already has focus. Ensure no window received the
6371// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006372TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006374 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006375 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006377 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006378
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006379 ASSERT_TRUE(mDispatcher->waitForIdle());
6380 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006381}
6382
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006383// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6384// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6385TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6386 const MotionEvent event =
6387 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6388 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006389 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006390 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6391 .build();
6392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6394 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6395
6396 ASSERT_TRUE(mDispatcher->waitForIdle());
6397 mFakePolicy->assertOnPointerDownWasNotCalled();
6398 // Ensure that the unfocused window did not receive any FOCUS events.
6399 mUnfocusedWindow->assertNoEvents();
6400}
6401
chaviwaf87b3e2019-10-01 16:59:28 -07006402// These tests ensures we can send touch events to a single client when there are multiple input
6403// windows that point to the same client token.
6404class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6405 virtual void SetUp() override {
6406 InputDispatcherTest::SetUp();
6407
Chris Yea209fde2020-07-22 13:54:51 -07006408 std::shared_ptr<FakeApplicationHandle> application =
6409 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006410 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6411 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006412 mWindow1->setFrame(Rect(0, 0, 100, 100));
6413
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006414 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6415 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006416 mWindow2->setFrame(Rect(100, 100, 200, 200));
6417
Arthur Hung72d8dc32020-03-28 00:48:39 +00006418 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006419 }
6420
6421protected:
6422 sp<FakeWindowHandle> mWindow1;
6423 sp<FakeWindowHandle> mWindow2;
6424
6425 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006426 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006427 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6428 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006429 }
6430
6431 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6432 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006433 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006434 InputEvent* event = window->consume();
6435
6436 ASSERT_NE(nullptr, event) << name.c_str()
6437 << ": consumer should have returned non-NULL event.";
6438
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006439 ASSERT_EQ(InputEventType::MOTION, event->getType())
6440 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006441
6442 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006443 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006444 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006445
6446 for (size_t i = 0; i < points.size(); i++) {
6447 float expectedX = points[i].x;
6448 float expectedY = points[i].y;
6449
6450 EXPECT_EQ(expectedX, motionEvent.getX(i))
6451 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6452 << ", got " << motionEvent.getX(i);
6453 EXPECT_EQ(expectedY, motionEvent.getY(i))
6454 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6455 << ", got " << motionEvent.getY(i);
6456 }
6457 }
chaviw9eaa22c2020-07-01 16:21:27 -07006458
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006459 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006460 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006461 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6462 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006463
6464 // Always consume from window1 since it's the window that has the InputReceiver
6465 consumeMotionEvent(mWindow1, action, expectedPoints);
6466 }
chaviwaf87b3e2019-10-01 16:59:28 -07006467};
6468
6469TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6470 // Touch Window 1
6471 PointF touchedPoint = {10, 10};
6472 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006473 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006474
6475 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006476 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006477
6478 // Touch Window 2
6479 touchedPoint = {150, 150};
6480 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006481 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006482}
6483
chaviw9eaa22c2020-07-01 16:21:27 -07006484TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6485 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006486 mWindow2->setWindowScale(0.5f, 0.5f);
6487
6488 // Touch Window 1
6489 PointF touchedPoint = {10, 10};
6490 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006491 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006492 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006493 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006494
6495 // Touch Window 2
6496 touchedPoint = {150, 150};
6497 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006498 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6499 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006500
chaviw9eaa22c2020-07-01 16:21:27 -07006501 // Update the transform so rotation is set
6502 mWindow2->setWindowTransform(0, -1, 1, 0);
6503 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6504 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006505}
6506
chaviw9eaa22c2020-07-01 16:21:27 -07006507TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006508 mWindow2->setWindowScale(0.5f, 0.5f);
6509
6510 // Touch Window 1
6511 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6512 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006513 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006514
6515 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006516 touchedPoints.push_back(PointF{150, 150});
6517 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006518 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006519
chaviw9eaa22c2020-07-01 16:21:27 -07006520 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006521 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006522 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006523
chaviw9eaa22c2020-07-01 16:21:27 -07006524 // Update the transform so rotation is set for Window 2
6525 mWindow2->setWindowTransform(0, -1, 1, 0);
6526 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006527 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006528}
6529
chaviw9eaa22c2020-07-01 16:21:27 -07006530TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006531 mWindow2->setWindowScale(0.5f, 0.5f);
6532
6533 // Touch Window 1
6534 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6535 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006536 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006537
6538 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006539 touchedPoints.push_back(PointF{150, 150});
6540 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006541
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006542 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006543
6544 // Move both windows
6545 touchedPoints = {{20, 20}, {175, 175}};
6546 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6547 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6548
chaviw9eaa22c2020-07-01 16:21:27 -07006549 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006550
chaviw9eaa22c2020-07-01 16:21:27 -07006551 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006552 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006553 expectedPoints.pop_back();
6554
6555 // Touch Window 2
6556 mWindow2->setWindowTransform(0, -1, 1, 0);
6557 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006558 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006559
6560 // Move both windows
6561 touchedPoints = {{20, 20}, {175, 175}};
6562 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6563 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6564
6565 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006566}
6567
6568TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6569 mWindow1->setWindowScale(0.5f, 0.5f);
6570
6571 // Touch Window 1
6572 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6573 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006574 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006575
6576 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006577 touchedPoints.push_back(PointF{150, 150});
6578 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006579
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006580 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006581
6582 // Move both windows
6583 touchedPoints = {{20, 20}, {175, 175}};
6584 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6585 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6586
chaviw9eaa22c2020-07-01 16:21:27 -07006587 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006588}
6589
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006590/**
6591 * When one of the windows is slippery, the touch should not slip into the other window with the
6592 * same input channel.
6593 */
6594TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6595 mWindow1->setSlippery(true);
6596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6597
6598 // Touch down in window 1
6599 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6600 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6601 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6602
6603 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6604 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6605 // getting generated.
6606 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6607 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6608
6609 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6610}
6611
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006612/**
6613 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6614 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6615 * that the pointer is hovering over may have a different transform.
6616 */
6617TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6618 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6619
6620 // Start hover in window 1
6621 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6622 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6623 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6624 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6625
6626 // Move hover to window 2.
6627 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6628 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6629
6630 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6631 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6632 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6633}
6634
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006635class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6636 virtual void SetUp() override {
6637 InputDispatcherTest::SetUp();
6638
Chris Yea209fde2020-07-22 13:54:51 -07006639 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006640 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006641 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6642 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006643 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006644 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006645 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006646
6647 // Set focused application.
6648 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6649
6650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006651 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006652 mWindow->consumeFocusEvent(true);
6653 }
6654
6655 virtual void TearDown() override {
6656 InputDispatcherTest::TearDown();
6657 mWindow.clear();
6658 }
6659
6660protected:
Chris Yea209fde2020-07-22 13:54:51 -07006661 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006662 sp<FakeWindowHandle> mWindow;
6663 static constexpr PointF WINDOW_LOCATION = {20, 20};
6664
6665 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006667 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6668 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006670 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6671 WINDOW_LOCATION));
6672 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006673
6674 sp<FakeWindowHandle> addSpyWindow() {
6675 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006676 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006677 spy->setTrustedOverlay(true);
6678 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006679 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006680 spy->setDispatchingTimeout(30ms);
6681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6682 return spy;
6683 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006684};
6685
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006686// Send a tap and respond, which should not cause an ANR.
6687TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6688 tapOnWindow();
6689 mWindow->consumeMotionDown();
6690 mWindow->consumeMotionUp();
6691 ASSERT_TRUE(mDispatcher->waitForIdle());
6692 mFakePolicy->assertNotifyAnrWasNotCalled();
6693}
6694
6695// Send a regular key and respond, which should not cause an ANR.
6696TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006698 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6699 ASSERT_TRUE(mDispatcher->waitForIdle());
6700 mFakePolicy->assertNotifyAnrWasNotCalled();
6701}
6702
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006703TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6704 mWindow->setFocusable(false);
6705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6706 mWindow->consumeFocusEvent(false);
6707
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006708 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006709 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006710 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms,
Harry Cutts33476232023-01-30 19:57:29 +00006711 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006713 // Key will not go to window because we have no focused window.
6714 // The 'no focused window' ANR timer should start instead.
6715
6716 // Now, the focused application goes away.
6717 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6718 // The key should get dropped and there should be no ANR.
6719
6720 ASSERT_TRUE(mDispatcher->waitForIdle());
6721 mFakePolicy->assertNotifyAnrWasNotCalled();
6722}
6723
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006724// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006725// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6726// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006727TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006729 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6730 WINDOW_LOCATION));
6731
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006732 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6733 ASSERT_TRUE(sequenceNum);
6734 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006735 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006736
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006737 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006738 mWindow->consumeMotionEvent(
6739 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006740 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006741 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006742}
6743
6744// Send a key to the app and have the app not respond right away.
6745TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6746 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006748 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6749 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006750 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006751 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006752 ASSERT_TRUE(mDispatcher->waitForIdle());
6753}
6754
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006755// We have a focused application, but no focused window
6756TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006757 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6759 mWindow->consumeFocusEvent(false);
6760
6761 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006763 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6764 WINDOW_LOCATION));
6765 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6766 mDispatcher->waitForIdle();
6767 mFakePolicy->assertNotifyAnrWasNotCalled();
6768
6769 // Once a focused event arrives, we get an ANR for this application
6770 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6771 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006772 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006773 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006774 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006775 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006776 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006777 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006778 ASSERT_TRUE(mDispatcher->waitForIdle());
6779}
6780
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006781/**
6782 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6783 * there will not be an ANR.
6784 */
6785TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6786 mWindow->setFocusable(false);
6787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6788 mWindow->consumeFocusEvent(false);
6789
6790 KeyEvent event;
6791 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6792 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6793
6794 // Define a valid key down event that is stale (too old).
6795 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006796 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006797 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006798
6799 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6800
6801 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006802 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006803 InputEventInjectionSync::WAIT_FOR_RESULT,
6804 INJECT_EVENT_TIMEOUT, policyFlags);
6805 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6806 << "Injection should fail because the event is stale";
6807
6808 ASSERT_TRUE(mDispatcher->waitForIdle());
6809 mFakePolicy->assertNotifyAnrWasNotCalled();
6810 mWindow->assertNoEvents();
6811}
6812
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006814// Make sure that we don't notify policy twice about the same ANR.
6815TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006816 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6818 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006819
6820 // Once a focused event arrives, we get an ANR for this application
6821 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6822 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006823 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006824 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006825 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006826 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006827 const std::chrono::duration appTimeout =
6828 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6829 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006830
Vishnu Naire4df8752022-09-08 09:17:55 -07006831 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006832 // ANR should not be raised again. It is up to policy to do that if it desires.
6833 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006834
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006835 // If we now get a focused window, the ANR should stop, but the policy handles that via
6836 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006837 ASSERT_TRUE(mDispatcher->waitForIdle());
6838}
6839
6840// We have a focused application, but no focused window
6841TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006842 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006843 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6844 mWindow->consumeFocusEvent(false);
6845
6846 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006847 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006848 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006849 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006850 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006851
Vishnu Naire4df8752022-09-08 09:17:55 -07006852 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6853 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006854
6855 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006856 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006857 ASSERT_TRUE(mDispatcher->waitForIdle());
6858 mWindow->assertNoEvents();
6859}
6860
6861/**
6862 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6863 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6864 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6865 * the ANR mechanism should still work.
6866 *
6867 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6868 * DOWN event, while not responding on the second one.
6869 */
6870TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6871 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6872 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6873 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6874 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6875 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006876 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006877
6878 // Now send ACTION_UP, with identical timestamp
6879 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6880 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6881 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6882 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006883 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884
6885 // We have now sent down and up. Let's consume first event and then ANR on the second.
6886 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6887 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006888 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006889}
6890
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006891// A spy window can receive an ANR
6892TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6893 sp<FakeWindowHandle> spy = addSpyWindow();
6894
6895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6896 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6897 WINDOW_LOCATION));
6898 mWindow->consumeMotionDown();
6899
6900 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6901 ASSERT_TRUE(sequenceNum);
6902 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006903 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006904
6905 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006906 spy->consumeMotionEvent(
6907 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006908 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006909 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006910}
6911
6912// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006913// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006914TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6915 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006916
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6918 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006919 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921
6922 // Stuck on the ACTION_UP
6923 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006924 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006926 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006927 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006928 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6929 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006930
6931 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6932 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006933 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006934 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006935 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006936}
6937
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006938// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006939// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006940TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6941 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006942
6943 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006944 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6945 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006946
6947 mWindow->consumeMotionDown();
6948 // Stuck on the ACTION_UP
6949 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006950 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006951
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006952 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006953 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006954 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6955 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006956
6957 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6958 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006959 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006960 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006961 spy->assertNoEvents();
6962}
6963
6964TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6965 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6966
6967 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6968
6969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6970 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6971 WINDOW_LOCATION));
6972
6973 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6974 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6975 ASSERT_TRUE(consumeSeq);
6976
Prabir Pradhanedd96402022-02-15 01:46:16 -08006977 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006978
6979 monitor.finishEvent(*consumeSeq);
6980 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6981
6982 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006983 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006984}
6985
6986// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6987// process events, you don't get an anr. When the window later becomes unresponsive again, you
6988// get an ANR again.
6989// 1. tap -> block on ACTION_UP -> receive ANR
6990// 2. consume all pending events (= queue becomes healthy again)
6991// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6992TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6993 tapOnWindow();
6994
6995 mWindow->consumeMotionDown();
6996 // Block on ACTION_UP
6997 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006998 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006999 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7000 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007001 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007002 mWindow->assertNoEvents();
7003
7004 tapOnWindow();
7005 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007006 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007007 mWindow->consumeMotionUp();
7008
7009 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007010 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007011 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007012 mWindow->assertNoEvents();
7013}
7014
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007015// If a connection remains unresponsive for a while, make sure policy is only notified once about
7016// it.
7017TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007019 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7020 WINDOW_LOCATION));
7021
7022 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007023 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007024 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007025 // 'notifyConnectionUnresponsive' should only be called once per connection
7026 mFakePolicy->assertNotifyAnrWasNotCalled();
7027 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007028 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007029 mWindow->consumeMotionEvent(
7030 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007031 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007032 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007033 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007034 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007035}
7036
7037/**
7038 * If a window is processing a motion event, and then a key event comes in, the key event should
7039 * not to to the focused window until the motion is processed.
7040 *
7041 * Warning!!!
7042 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7043 * and the injection timeout that we specify when injecting the key.
7044 * We must have the injection timeout (10ms) be smaller than
7045 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7046 *
7047 * If that value changes, this test should also change.
7048 */
7049TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7050 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7052
7053 tapOnWindow();
7054 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7055 ASSERT_TRUE(downSequenceNum);
7056 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7057 ASSERT_TRUE(upSequenceNum);
7058 // Don't finish the events yet, and send a key
7059 // Injection will "succeed" because we will eventually give up and send the key to the focused
7060 // window even if motions are still being processed. But because the injection timeout is short,
7061 // we will receive INJECTION_TIMED_OUT as the result.
7062
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007063 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007064 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007065 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007066 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007067 // Key will not be sent to the window, yet, because the window is still processing events
7068 // and the key remains pending, waiting for the touch events to be processed
7069 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7070 ASSERT_FALSE(keySequenceNum);
7071
7072 std::this_thread::sleep_for(500ms);
7073 // if we wait long enough though, dispatcher will give up, and still send the key
7074 // to the focused window, even though we have not yet finished the motion event
7075 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7076 mWindow->finishEvent(*downSequenceNum);
7077 mWindow->finishEvent(*upSequenceNum);
7078}
7079
7080/**
7081 * If a window is processing a motion event, and then a key event comes in, the key event should
7082 * not go to the focused window until the motion is processed.
7083 * If then a new motion comes in, then the pending key event should be going to the currently
7084 * focused window right away.
7085 */
7086TEST_F(InputDispatcherSingleWindowAnr,
7087 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7088 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7089 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7090
7091 tapOnWindow();
7092 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7093 ASSERT_TRUE(downSequenceNum);
7094 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7095 ASSERT_TRUE(upSequenceNum);
7096 // Don't finish the events yet, and send a key
7097 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007099 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7100 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007101 // At this point, key is still pending, and should not be sent to the application yet.
7102 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7103 ASSERT_FALSE(keySequenceNum);
7104
7105 // Now tap down again. It should cause the pending key to go to the focused window right away.
7106 tapOnWindow();
7107 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7108 // the other events yet. We can finish events in any order.
7109 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7110 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7111 mWindow->consumeMotionDown();
7112 mWindow->consumeMotionUp();
7113 mWindow->assertNoEvents();
7114}
7115
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007116/**
7117 * Send an event to the app and have the app not respond right away.
7118 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7119 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7120 * At some point, the window becomes responsive again.
7121 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7122 */
7123TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7125 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7126 .build());
7127
7128 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7129 ASSERT_TRUE(sequenceNum);
7130 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7131 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7132
7133 mWindow->finishEvent(*sequenceNum);
7134 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7135 ASSERT_TRUE(mDispatcher->waitForIdle());
7136 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7137
7138 // Now that the window is responsive, let's continue the gesture.
7139 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7140 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7141 .build());
7142
7143 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7144 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7145 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7146 .build());
7147
7148 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7149 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7150 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7151 .build());
7152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7153 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7154 .build());
7155 // We already canceled this pointer, so the window shouldn't get any new events.
7156 mWindow->assertNoEvents();
7157
7158 // Start another one.
7159 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7160 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7161 .build());
7162 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7163}
7164
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007165class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7166 virtual void SetUp() override {
7167 InputDispatcherTest::SetUp();
7168
Chris Yea209fde2020-07-22 13:54:51 -07007169 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007170 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007171 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7172 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007173 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007174 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007175 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007176
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007177 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7178 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007179 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007180 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007181
7182 // Set focused application.
7183 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007184 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007185
7186 // Expect one focus window exist in display.
7187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007188 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007189 mFocusedWindow->consumeFocusEvent(true);
7190 }
7191
7192 virtual void TearDown() override {
7193 InputDispatcherTest::TearDown();
7194
7195 mUnfocusedWindow.clear();
7196 mFocusedWindow.clear();
7197 }
7198
7199protected:
Chris Yea209fde2020-07-22 13:54:51 -07007200 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007201 sp<FakeWindowHandle> mUnfocusedWindow;
7202 sp<FakeWindowHandle> mFocusedWindow;
7203 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7204 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7205 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7206
7207 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7208
7209 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7210
7211private:
7212 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007214 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7215 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007217 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7218 location));
7219 }
7220};
7221
7222// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7223// should be ANR'd first.
7224TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007226 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7227 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007229 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007230 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007231 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007232 // We consumed all events, so no ANR
7233 ASSERT_TRUE(mDispatcher->waitForIdle());
7234 mFakePolicy->assertNotifyAnrWasNotCalled();
7235
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007237 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7238 FOCUSED_WINDOW_LOCATION));
7239 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7240 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007241
7242 const std::chrono::duration timeout =
7243 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007244 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007245 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7246 // sequence to make it consistent
7247 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007248 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007249 mFocusedWindow->consumeMotionDown();
7250 // This cancel is generated because the connection was unresponsive
7251 mFocusedWindow->consumeMotionCancel();
7252 mFocusedWindow->assertNoEvents();
7253 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007254 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007255 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7256 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007257 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007258}
7259
7260// If we have 2 windows with identical timeouts that are both unresponsive,
7261// it doesn't matter which order they should have ANR.
7262// But we should receive ANR for both.
7263TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7264 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007265 mUnfocusedWindow->setDispatchingTimeout(
7266 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007267 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7268
7269 tapOnFocusedWindow();
7270 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007271 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007272 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7273 mFocusedWindow->getDispatchingTimeout(
7274 DISPATCHING_TIMEOUT)),
7275 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7276
7277 ASSERT_THAT(anrConnectionTokens,
7278 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7279 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007280
7281 ASSERT_TRUE(mDispatcher->waitForIdle());
7282 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007283
7284 mFocusedWindow->consumeMotionDown();
7285 mFocusedWindow->consumeMotionUp();
7286 mUnfocusedWindow->consumeMotionOutside();
7287
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007288 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7289 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007290
7291 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007292 ASSERT_THAT(responsiveTokens,
7293 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7294 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007295 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007296}
7297
7298// If a window is already not responding, the second tap on the same window should be ignored.
7299// We should also log an error to account for the dropped event (not tested here).
7300// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7301TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7302 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007303 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007304 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007305 // Receive the events, but don't respond
7306 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7307 ASSERT_TRUE(downEventSequenceNum);
7308 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7309 ASSERT_TRUE(upEventSequenceNum);
7310 const std::chrono::duration timeout =
7311 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007312 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007313
7314 // Tap once again
7315 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007317 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7318 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007319 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007320 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7321 FOCUSED_WINDOW_LOCATION));
7322 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7323 // valid touch target
7324 mUnfocusedWindow->assertNoEvents();
7325
7326 // Consume the first tap
7327 mFocusedWindow->finishEvent(*downEventSequenceNum);
7328 mFocusedWindow->finishEvent(*upEventSequenceNum);
7329 ASSERT_TRUE(mDispatcher->waitForIdle());
7330 // The second tap did not go to the focused window
7331 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007332 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007333 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7334 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007335 mFakePolicy->assertNotifyAnrWasNotCalled();
7336}
7337
7338// If you tap outside of all windows, there will not be ANR
7339TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007340 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007341 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7342 LOCATION_OUTSIDE_ALL_WINDOWS));
7343 ASSERT_TRUE(mDispatcher->waitForIdle());
7344 mFakePolicy->assertNotifyAnrWasNotCalled();
7345}
7346
7347// Since the focused window is paused, tapping on it should not produce any events
7348TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7349 mFocusedWindow->setPaused(true);
7350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7351
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007352 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007353 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7354 FOCUSED_WINDOW_LOCATION));
7355
7356 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7357 ASSERT_TRUE(mDispatcher->waitForIdle());
7358 // Should not ANR because the window is paused, and touches shouldn't go to it
7359 mFakePolicy->assertNotifyAnrWasNotCalled();
7360
7361 mFocusedWindow->assertNoEvents();
7362 mUnfocusedWindow->assertNoEvents();
7363}
7364
7365/**
7366 * If a window is processing a motion event, and then a key event comes in, the key event should
7367 * not to to the focused window until the motion is processed.
7368 * If a different window becomes focused at this time, the key should go to that window instead.
7369 *
7370 * Warning!!!
7371 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7372 * and the injection timeout that we specify when injecting the key.
7373 * We must have the injection timeout (10ms) be smaller than
7374 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7375 *
7376 * If that value changes, this test should also change.
7377 */
7378TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7379 // Set a long ANR timeout to prevent it from triggering
7380 mFocusedWindow->setDispatchingTimeout(2s);
7381 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7382
7383 tapOnUnfocusedWindow();
7384 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7385 ASSERT_TRUE(downSequenceNum);
7386 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7387 ASSERT_TRUE(upSequenceNum);
7388 // Don't finish the events yet, and send a key
7389 // Injection will succeed because we will eventually give up and send the key to the focused
7390 // window even if motions are still being processed.
7391
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007392 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007393 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007394 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007396 // Key will not be sent to the window, yet, because the window is still processing events
7397 // and the key remains pending, waiting for the touch events to be processed
7398 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7399 ASSERT_FALSE(keySequenceNum);
7400
7401 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007402 mFocusedWindow->setFocusable(false);
7403 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007404 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007405 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007406
7407 // Focus events should precede the key events
7408 mUnfocusedWindow->consumeFocusEvent(true);
7409 mFocusedWindow->consumeFocusEvent(false);
7410
7411 // Finish the tap events, which should unblock dispatcher
7412 mUnfocusedWindow->finishEvent(*downSequenceNum);
7413 mUnfocusedWindow->finishEvent(*upSequenceNum);
7414
7415 // Now that all queues are cleared and no backlog in the connections, the key event
7416 // can finally go to the newly focused "mUnfocusedWindow".
7417 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7418 mFocusedWindow->assertNoEvents();
7419 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007420 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007421}
7422
7423// When the touch stream is split across 2 windows, and one of them does not respond,
7424// then ANR should be raised and the touch should be canceled for the unresponsive window.
7425// The other window should not be affected by that.
7426TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7427 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007428 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7429 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7430 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007431 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007432 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007433
7434 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007435 mDispatcher->notifyMotion(
7436 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7437 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007438
7439 const std::chrono::duration timeout =
7440 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007441 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007442
7443 mUnfocusedWindow->consumeMotionDown();
7444 mFocusedWindow->consumeMotionDown();
7445 // Focused window may or may not receive ACTION_MOVE
7446 // But it should definitely receive ACTION_CANCEL due to the ANR
7447 InputEvent* event;
7448 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7449 ASSERT_TRUE(moveOrCancelSequenceNum);
7450 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7451 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007452 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007453 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7454 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7455 mFocusedWindow->consumeMotionCancel();
7456 } else {
7457 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7458 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007459 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007460 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7461 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007462
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007463 mUnfocusedWindow->assertNoEvents();
7464 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007465 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007466}
7467
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007468/**
7469 * If we have no focused window, and a key comes in, we start the ANR timer.
7470 * The focused application should add a focused window before the timer runs out to prevent ANR.
7471 *
7472 * If the user touches another application during this time, the key should be dropped.
7473 * Next, if a new focused window comes in, without toggling the focused application,
7474 * then no ANR should occur.
7475 *
7476 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7477 * but in some cases the policy may not update the focused application.
7478 */
7479TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7480 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7481 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007482 focusedApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007483 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7484 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7485 mFocusedWindow->setFocusable(false);
7486
7487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7488 mFocusedWindow->consumeFocusEvent(false);
7489
7490 // Send a key. The ANR timer should start because there is no focused window.
7491 // 'focusedApplication' will get blamed if this timer completes.
7492 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007493 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007494 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007495 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms,
Harry Cutts33476232023-01-30 19:57:29 +00007496 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007498
7499 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7500 // then the injected touches won't cause the focused event to get dropped.
7501 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7502 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7503 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7504 // For this test, it means that the key would get delivered to the window once it becomes
7505 // focused.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007506 std::this_thread::sleep_for(50ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007507
7508 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007509 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7510 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7511 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007512
7513 // We do not consume the motion right away, because that would require dispatcher to first
7514 // process (== drop) the key event, and by that time, ANR will be raised.
7515 // Set the focused window first.
7516 mFocusedWindow->setFocusable(true);
7517 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7518 setFocusedWindow(mFocusedWindow);
7519 mFocusedWindow->consumeFocusEvent(true);
7520 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7521 // to another application. This could be a bug / behaviour in the policy.
7522
7523 mUnfocusedWindow->consumeMotionDown();
7524
7525 ASSERT_TRUE(mDispatcher->waitForIdle());
7526 // Should not ANR because we actually have a focused window. It was just added too slowly.
7527 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7528}
7529
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007530// These tests ensure we cannot send touch events to a window that's positioned behind a window
7531// that has feature NO_INPUT_CHANNEL.
7532// Layout:
7533// Top (closest to user)
7534// mNoInputWindow (above all windows)
7535// mBottomWindow
7536// Bottom (furthest from user)
7537class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7538 virtual void SetUp() override {
7539 InputDispatcherTest::SetUp();
7540
7541 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007542 mNoInputWindow =
7543 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7544 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007545 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007546 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007547 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7548 // It's perfectly valid for this window to not have an associated input channel
7549
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007550 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7551 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007552 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7553
7554 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7555 }
7556
7557protected:
7558 std::shared_ptr<FakeApplicationHandle> mApplication;
7559 sp<FakeWindowHandle> mNoInputWindow;
7560 sp<FakeWindowHandle> mBottomWindow;
7561};
7562
7563TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7564 PointF touchedPoint = {10, 10};
7565
Prabir Pradhan678438e2023-04-13 19:32:51 +00007566 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7567 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7568 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007569
7570 mNoInputWindow->assertNoEvents();
7571 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7572 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7573 // and therefore should prevent mBottomWindow from receiving touches
7574 mBottomWindow->assertNoEvents();
7575}
7576
7577/**
7578 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7579 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7580 */
7581TEST_F(InputDispatcherMultiWindowOcclusionTests,
7582 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007583 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7584 "Window with input channel and NO_INPUT_CHANNEL",
7585 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007586
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007587 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007588 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7590
7591 PointF touchedPoint = {10, 10};
7592
Prabir Pradhan678438e2023-04-13 19:32:51 +00007593 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7594 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7595 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007596
7597 mNoInputWindow->assertNoEvents();
7598 mBottomWindow->assertNoEvents();
7599}
7600
Vishnu Nair958da932020-08-21 17:12:37 -07007601class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7602protected:
7603 std::shared_ptr<FakeApplicationHandle> mApp;
7604 sp<FakeWindowHandle> mWindow;
7605 sp<FakeWindowHandle> mMirror;
7606
7607 virtual void SetUp() override {
7608 InputDispatcherTest::SetUp();
7609 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007610 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7611 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7612 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007613 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7614 mWindow->setFocusable(true);
7615 mMirror->setFocusable(true);
7616 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7617 }
7618};
7619
7620TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7621 // Request focus on a mirrored window
7622 setFocusedWindow(mMirror);
7623
7624 // window gets focused
7625 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7627 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007628 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7629}
7630
7631// A focused & mirrored window remains focused only if the window and its mirror are both
7632// focusable.
7633TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7634 setFocusedWindow(mMirror);
7635
7636 // window gets focused
7637 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7639 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007640 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007643 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7644
7645 mMirror->setFocusable(false);
7646 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7647
7648 // window loses focus since one of the windows associated with the token in not focusable
7649 mWindow->consumeFocusEvent(false);
7650
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007651 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7652 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007653 mWindow->assertNoEvents();
7654}
7655
7656// A focused & mirrored window remains focused until the window and its mirror both become
7657// invisible.
7658TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7659 setFocusedWindow(mMirror);
7660
7661 // window gets focused
7662 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7664 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007665 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7667 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007668 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7669
7670 mMirror->setVisible(false);
7671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7672
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7674 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007675 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7677 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007678 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7679
7680 mWindow->setVisible(false);
7681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7682
7683 // window loses focus only after all windows associated with the token become invisible.
7684 mWindow->consumeFocusEvent(false);
7685
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7687 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007688 mWindow->assertNoEvents();
7689}
7690
7691// A focused & mirrored window remains focused until both windows are removed.
7692TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7693 setFocusedWindow(mMirror);
7694
7695 // window gets focused
7696 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7698 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007699 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7701 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007702 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7703
7704 // single window is removed but the window token remains focused
7705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7706
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7708 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007709 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7711 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007712 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7713
7714 // Both windows are removed
7715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7716 mWindow->consumeFocusEvent(false);
7717
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007718 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7719 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007720 mWindow->assertNoEvents();
7721}
7722
7723// Focus request can be pending until one window becomes visible.
7724TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7725 // Request focus on an invisible mirror.
7726 mWindow->setVisible(false);
7727 mMirror->setVisible(false);
7728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7729 setFocusedWindow(mMirror);
7730
7731 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007733 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7734 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007735
7736 mMirror->setVisible(true);
7737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7738
7739 // window gets focused
7740 mWindow->consumeFocusEvent(true);
7741 // window gets the pending key event
7742 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7743}
Prabir Pradhan99987712020-11-10 18:43:05 -08007744
7745class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7746protected:
7747 std::shared_ptr<FakeApplicationHandle> mApp;
7748 sp<FakeWindowHandle> mWindow;
7749 sp<FakeWindowHandle> mSecondWindow;
7750
7751 void SetUp() override {
7752 InputDispatcherTest::SetUp();
7753 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007754 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007755 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007756 mSecondWindow =
7757 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007758 mSecondWindow->setFocusable(true);
7759
7760 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7762
7763 setFocusedWindow(mWindow);
7764 mWindow->consumeFocusEvent(true);
7765 }
7766
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007767 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007768 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007769 }
7770
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007771 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7772 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007773 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007774 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7775 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007776 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007777 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007778 }
7779};
7780
7781TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7782 // Ensure that capture cannot be obtained for unfocused windows.
7783 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7784 mFakePolicy->assertSetPointerCaptureNotCalled();
7785 mSecondWindow->assertNoEvents();
7786
7787 // Ensure that capture can be enabled from the focus window.
7788 requestAndVerifyPointerCapture(mWindow, true);
7789
7790 // Ensure that capture cannot be disabled from a window that does not have capture.
7791 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7792 mFakePolicy->assertSetPointerCaptureNotCalled();
7793
7794 // Ensure that capture can be disabled from the window with capture.
7795 requestAndVerifyPointerCapture(mWindow, false);
7796}
7797
7798TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007799 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007800
7801 setFocusedWindow(mSecondWindow);
7802
7803 // Ensure that the capture disabled event was sent first.
7804 mWindow->consumeCaptureEvent(false);
7805 mWindow->consumeFocusEvent(false);
7806 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007807 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007808
7809 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007810 notifyPointerCaptureChanged({});
7811 notifyPointerCaptureChanged(request);
7812 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007813 mWindow->assertNoEvents();
7814 mSecondWindow->assertNoEvents();
7815 mFakePolicy->assertSetPointerCaptureNotCalled();
7816}
7817
7818TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007819 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007820
7821 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007822 notifyPointerCaptureChanged({});
7823 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007824
7825 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007826 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007827 mWindow->consumeCaptureEvent(false);
7828 mWindow->assertNoEvents();
7829}
7830
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007831TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7832 requestAndVerifyPointerCapture(mWindow, true);
7833
7834 // The first window loses focus.
7835 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007836 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007837 mWindow->consumeCaptureEvent(false);
7838
7839 // Request Pointer Capture from the second window before the notification from InputReader
7840 // arrives.
7841 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007842 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007843
7844 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007845 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007846
7847 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007848 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007849
7850 mSecondWindow->consumeFocusEvent(true);
7851 mSecondWindow->consumeCaptureEvent(true);
7852}
7853
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007854TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7855 // App repeatedly enables and disables capture.
7856 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7857 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7858 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7859 mFakePolicy->assertSetPointerCaptureCalled(false);
7860 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7861 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7862
7863 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7864 // first request is now stale, this should do nothing.
7865 notifyPointerCaptureChanged(firstRequest);
7866 mWindow->assertNoEvents();
7867
7868 // InputReader notifies that the second request was enabled.
7869 notifyPointerCaptureChanged(secondRequest);
7870 mWindow->consumeCaptureEvent(true);
7871}
7872
Prabir Pradhan7092e262022-05-03 16:51:09 +00007873TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7874 requestAndVerifyPointerCapture(mWindow, true);
7875
7876 // App toggles pointer capture off and on.
7877 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7878 mFakePolicy->assertSetPointerCaptureCalled(false);
7879
7880 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7881 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7882
7883 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7884 // preceding "disable" request.
7885 notifyPointerCaptureChanged(enableRequest);
7886
7887 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7888 // any notifications.
7889 mWindow->assertNoEvents();
7890}
7891
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007892class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7893protected:
7894 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007895
7896 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7897 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7898
7899 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7900 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7901
7902 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7903 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7904 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7905 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7906 MAXIMUM_OBSCURING_OPACITY);
7907
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007908 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7909 static constexpr gui::Uid APP_B_UID{10002};
7910 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007911
7912 sp<FakeWindowHandle> mTouchWindow;
7913
7914 virtual void SetUp() override {
7915 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007916 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007917 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7918 }
7919
7920 virtual void TearDown() override {
7921 InputDispatcherTest::TearDown();
7922 mTouchWindow.clear();
7923 }
7924
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007925 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007926 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007927 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007928 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007929 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007930 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007931 return window;
7932 }
7933
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007934 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007935 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7936 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007937 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007938 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007939 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007940 return window;
7941 }
7942
7943 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007944 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7945 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7946 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007947 }
7948};
7949
7950TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007951 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007952 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007953 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007954
7955 touch();
7956
7957 mTouchWindow->assertNoEvents();
7958}
7959
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007960TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007961 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7962 const sp<FakeWindowHandle>& w =
7963 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7965
7966 touch();
7967
7968 mTouchWindow->assertNoEvents();
7969}
7970
7971TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007972 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7973 const sp<FakeWindowHandle>& w =
7974 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7976
7977 touch();
7978
7979 w->assertNoEvents();
7980}
7981
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007982TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007983 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7984 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007985
7986 touch();
7987
7988 mTouchWindow->consumeAnyMotionDown();
7989}
7990
7991TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007992 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007993 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007994 w->setFrame(Rect(0, 0, 50, 50));
7995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007996
7997 touch({PointF{100, 100}});
7998
7999 mTouchWindow->consumeAnyMotionDown();
8000}
8001
8002TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008003 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008004 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8006
8007 touch();
8008
8009 mTouchWindow->consumeAnyMotionDown();
8010}
8011
8012TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8013 const sp<FakeWindowHandle>& w =
8014 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
8015 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008016
8017 touch();
8018
8019 mTouchWindow->consumeAnyMotionDown();
8020}
8021
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008022TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8023 const sp<FakeWindowHandle>& w =
8024 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
8025 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8026
8027 touch();
8028
8029 w->assertNoEvents();
8030}
8031
8032/**
8033 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8034 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8035 * window, the occluding window will still receive ACTION_OUTSIDE event.
8036 */
8037TEST_F(InputDispatcherUntrustedTouchesTest,
8038 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8039 const sp<FakeWindowHandle>& w =
8040 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008041 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008042 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8043
8044 touch();
8045
8046 w->consumeMotionOutside();
8047}
8048
8049TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8050 const sp<FakeWindowHandle>& w =
8051 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008052 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8054
8055 touch();
8056
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008057 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008058}
8059
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008060TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008061 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008062 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8063 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008064 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8065
8066 touch();
8067
8068 mTouchWindow->consumeAnyMotionDown();
8069}
8070
8071TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8072 const sp<FakeWindowHandle>& w =
8073 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8074 MAXIMUM_OBSCURING_OPACITY);
8075 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008076
8077 touch();
8078
8079 mTouchWindow->consumeAnyMotionDown();
8080}
8081
8082TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008083 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008084 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8085 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008086 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8087
8088 touch();
8089
8090 mTouchWindow->assertNoEvents();
8091}
8092
8093TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8094 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8095 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008096 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8097 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008098 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008099 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8100 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008101 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8102
8103 touch();
8104
8105 mTouchWindow->assertNoEvents();
8106}
8107
8108TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8109 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8110 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008111 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8112 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008113 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008114 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8115 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008116 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8117
8118 touch();
8119
8120 mTouchWindow->consumeAnyMotionDown();
8121}
8122
8123TEST_F(InputDispatcherUntrustedTouchesTest,
8124 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8125 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008126 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8127 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008128 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008129 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8130 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008131 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8132
8133 touch();
8134
8135 mTouchWindow->consumeAnyMotionDown();
8136}
8137
8138TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8139 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008140 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8141 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008142 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008143 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8144 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008146
8147 touch();
8148
8149 mTouchWindow->assertNoEvents();
8150}
8151
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008152TEST_F(InputDispatcherUntrustedTouchesTest,
8153 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8154 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008155 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8156 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008157 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008158 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8159 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8161
8162 touch();
8163
8164 mTouchWindow->assertNoEvents();
8165}
8166
8167TEST_F(InputDispatcherUntrustedTouchesTest,
8168 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8169 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008170 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8171 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008172 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008173 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8174 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008175 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8176
8177 touch();
8178
8179 mTouchWindow->consumeAnyMotionDown();
8180}
8181
8182TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8183 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008184 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8185 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8187
8188 touch();
8189
8190 mTouchWindow->consumeAnyMotionDown();
8191}
8192
8193TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8194 const sp<FakeWindowHandle>& w =
8195 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8196 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8197
8198 touch();
8199
8200 mTouchWindow->consumeAnyMotionDown();
8201}
8202
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008203TEST_F(InputDispatcherUntrustedTouchesTest,
8204 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8205 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8206 const sp<FakeWindowHandle>& w =
8207 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8208 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8209
8210 touch();
8211
8212 mTouchWindow->assertNoEvents();
8213}
8214
8215TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8216 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8217 const sp<FakeWindowHandle>& w =
8218 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8219 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8220
8221 touch();
8222
8223 mTouchWindow->consumeAnyMotionDown();
8224}
8225
8226TEST_F(InputDispatcherUntrustedTouchesTest,
8227 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8228 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8229 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008230 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8231 OPACITY_ABOVE_THRESHOLD);
8232 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8233
8234 touch();
8235
8236 mTouchWindow->consumeAnyMotionDown();
8237}
8238
8239TEST_F(InputDispatcherUntrustedTouchesTest,
8240 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8241 const sp<FakeWindowHandle>& w1 =
8242 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8243 OPACITY_BELOW_THRESHOLD);
8244 const sp<FakeWindowHandle>& w2 =
8245 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8246 OPACITY_BELOW_THRESHOLD);
8247 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8248
8249 touch();
8250
8251 mTouchWindow->assertNoEvents();
8252}
8253
8254/**
8255 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8256 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8257 * (which alone would result in allowing touches) does not affect the blocking behavior.
8258 */
8259TEST_F(InputDispatcherUntrustedTouchesTest,
8260 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8261 const sp<FakeWindowHandle>& wB =
8262 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8263 OPACITY_BELOW_THRESHOLD);
8264 const sp<FakeWindowHandle>& wC =
8265 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8266 OPACITY_BELOW_THRESHOLD);
8267 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8268
8269 touch();
8270
8271 mTouchWindow->assertNoEvents();
8272}
8273
8274/**
8275 * This test is testing that a window from a different UID but with same application token doesn't
8276 * block the touch. Apps can share the application token for close UI collaboration for example.
8277 */
8278TEST_F(InputDispatcherUntrustedTouchesTest,
8279 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8280 const sp<FakeWindowHandle>& w =
8281 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8282 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8284
8285 touch();
8286
8287 mTouchWindow->consumeAnyMotionDown();
8288}
8289
arthurhungb89ccb02020-12-30 16:19:01 +08008290class InputDispatcherDragTests : public InputDispatcherTest {
8291protected:
8292 std::shared_ptr<FakeApplicationHandle> mApp;
8293 sp<FakeWindowHandle> mWindow;
8294 sp<FakeWindowHandle> mSecondWindow;
8295 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008296 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008297 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8298 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008299
8300 void SetUp() override {
8301 InputDispatcherTest::SetUp();
8302 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008303 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008304 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008305
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008306 mSecondWindow =
8307 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008308 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008309
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008310 mSpyWindow =
8311 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008312 mSpyWindow->setSpy(true);
8313 mSpyWindow->setTrustedOverlay(true);
8314 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8315
arthurhungb89ccb02020-12-30 16:19:01 +08008316 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008317 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008318 }
8319
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008320 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8321 switch (fromSource) {
8322 case AINPUT_SOURCE_TOUCHSCREEN:
8323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8324 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8325 ADISPLAY_ID_DEFAULT, {50, 50}))
8326 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8327 break;
8328 case AINPUT_SOURCE_STYLUS:
8329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8330 injectMotionEvent(
8331 mDispatcher,
8332 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8333 AINPUT_SOURCE_STYLUS)
8334 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008335 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008336 .x(50)
8337 .y(50))
8338 .build()));
8339 break;
8340 case AINPUT_SOURCE_MOUSE:
8341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8342 injectMotionEvent(
8343 mDispatcher,
8344 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8345 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8346 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008347 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008348 .x(50)
8349 .y(50))
8350 .build()));
8351 break;
8352 default:
8353 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8354 }
arthurhungb89ccb02020-12-30 16:19:01 +08008355
8356 // Window should receive motion event.
8357 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008358 // Spy window should also receive motion event
8359 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008360 }
8361
8362 // Start performing drag, we will create a drag window and transfer touch to it.
8363 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8364 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008365 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008366 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008367 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008368 }
arthurhungb89ccb02020-12-30 16:19:01 +08008369
8370 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008371 mDragWindow =
8372 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008373 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008374 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008375 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008376
8377 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008378 bool transferred =
8379 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008380 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008381 if (transferred) {
8382 mWindow->consumeMotionCancel();
8383 mDragWindow->consumeMotionDown();
8384 }
8385 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008386 }
8387};
8388
8389TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008390 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008391
8392 // Move on window.
8393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8394 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8395 ADISPLAY_ID_DEFAULT, {50, 50}))
8396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8397 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8398 mWindow->consumeDragEvent(false, 50, 50);
8399 mSecondWindow->assertNoEvents();
8400
8401 // Move to another window.
8402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8403 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8404 ADISPLAY_ID_DEFAULT, {150, 50}))
8405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8406 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8407 mWindow->consumeDragEvent(true, 150, 50);
8408 mSecondWindow->consumeDragEvent(false, 50, 50);
8409
8410 // Move back to original window.
8411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8412 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8413 ADISPLAY_ID_DEFAULT, {50, 50}))
8414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8415 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8416 mWindow->consumeDragEvent(false, 50, 50);
8417 mSecondWindow->consumeDragEvent(true, -50, 50);
8418
8419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8420 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8421 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8422 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8423 mWindow->assertNoEvents();
8424 mSecondWindow->assertNoEvents();
8425}
8426
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008427TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008428 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008429
8430 // No cancel event after drag start
8431 mSpyWindow->assertNoEvents();
8432
8433 const MotionEvent secondFingerDownEvent =
8434 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8435 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008436 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8437 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008438 .build();
8439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8440 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8441 InputEventInjectionSync::WAIT_FOR_RESULT))
8442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8443
8444 // Receives cancel for first pointer after next pointer down
8445 mSpyWindow->consumeMotionCancel();
8446 mSpyWindow->consumeMotionDown();
8447
8448 mSpyWindow->assertNoEvents();
8449}
8450
arthurhungf452d0b2021-01-06 00:19:52 +08008451TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008452 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008453
8454 // Move on window.
8455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8456 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8457 ADISPLAY_ID_DEFAULT, {50, 50}))
8458 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8459 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8460 mWindow->consumeDragEvent(false, 50, 50);
8461 mSecondWindow->assertNoEvents();
8462
8463 // Move to another window.
8464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8465 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8466 ADISPLAY_ID_DEFAULT, {150, 50}))
8467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8468 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8469 mWindow->consumeDragEvent(true, 150, 50);
8470 mSecondWindow->consumeDragEvent(false, 50, 50);
8471
8472 // drop to another window.
8473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8474 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8475 {150, 50}))
8476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8477 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008478 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008479 mWindow->assertNoEvents();
8480 mSecondWindow->assertNoEvents();
8481}
8482
arthurhung6d4bed92021-03-17 11:59:33 +08008483TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008484 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008485
8486 // Move on window and keep button pressed.
8487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8488 injectMotionEvent(mDispatcher,
8489 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8490 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008491 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008492 .build()))
8493 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8494 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8495 mWindow->consumeDragEvent(false, 50, 50);
8496 mSecondWindow->assertNoEvents();
8497
8498 // Move to another window and release button, expect to drop item.
8499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8500 injectMotionEvent(mDispatcher,
8501 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8502 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008503 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008504 .build()))
8505 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8506 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8507 mWindow->assertNoEvents();
8508 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008509 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008510
8511 // nothing to the window.
8512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8513 injectMotionEvent(mDispatcher,
8514 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8515 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008516 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008517 .build()))
8518 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8519 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8520 mWindow->assertNoEvents();
8521 mSecondWindow->assertNoEvents();
8522}
8523
Arthur Hung54745652022-04-20 07:17:41 +00008524TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008525 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008526
8527 // Set second window invisible.
8528 mSecondWindow->setVisible(false);
8529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8530
8531 // Move on window.
8532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8533 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8534 ADISPLAY_ID_DEFAULT, {50, 50}))
8535 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8536 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8537 mWindow->consumeDragEvent(false, 50, 50);
8538 mSecondWindow->assertNoEvents();
8539
8540 // Move to another window.
8541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8542 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8543 ADISPLAY_ID_DEFAULT, {150, 50}))
8544 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8545 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8546 mWindow->consumeDragEvent(true, 150, 50);
8547 mSecondWindow->assertNoEvents();
8548
8549 // drop to another window.
8550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8551 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8552 {150, 50}))
8553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8554 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008555 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008556 mWindow->assertNoEvents();
8557 mSecondWindow->assertNoEvents();
8558}
8559
Arthur Hung54745652022-04-20 07:17:41 +00008560TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008561 // Ensure window could track pointerIds if it didn't support split touch.
8562 mWindow->setPreventSplitting(true);
8563
Arthur Hung54745652022-04-20 07:17:41 +00008564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8565 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8566 {50, 50}))
8567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8568 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8569
8570 const MotionEvent secondFingerDownEvent =
8571 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8572 .displayId(ADISPLAY_ID_DEFAULT)
8573 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008574 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8575 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008576 .build();
8577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8578 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8579 InputEventInjectionSync::WAIT_FOR_RESULT))
8580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008581 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008582
8583 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008584 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008585}
8586
8587TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8588 // First down on second window.
8589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8590 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8591 {150, 50}))
8592 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8593
8594 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8595
8596 // Second down on first window.
8597 const MotionEvent secondFingerDownEvent =
8598 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8599 .displayId(ADISPLAY_ID_DEFAULT)
8600 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008601 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8602 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008603 .build();
8604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8605 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8606 InputEventInjectionSync::WAIT_FOR_RESULT))
8607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8608 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8609
8610 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008611 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008612
8613 // Move on window.
8614 const MotionEvent secondFingerMoveEvent =
8615 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8616 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008617 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8618 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008619 .build();
8620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8621 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8622 InputEventInjectionSync::WAIT_FOR_RESULT));
8623 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8624 mWindow->consumeDragEvent(false, 50, 50);
8625 mSecondWindow->consumeMotionMove();
8626
8627 // Release the drag pointer should perform drop.
8628 const MotionEvent secondFingerUpEvent =
8629 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8630 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008631 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8632 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008633 .build();
8634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8635 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8636 InputEventInjectionSync::WAIT_FOR_RESULT));
8637 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008638 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008639 mWindow->assertNoEvents();
8640 mSecondWindow->consumeMotionMove();
8641}
8642
Arthur Hung3915c1f2022-05-31 07:17:17 +00008643TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008644 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008645
8646 // Update window of second display.
8647 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008648 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008649 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8650
8651 // Let second display has a touch state.
8652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8653 injectMotionEvent(mDispatcher,
8654 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8655 AINPUT_SOURCE_TOUCHSCREEN)
8656 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008657 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008658 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008659 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008660 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008661 // Update window again.
8662 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8663
8664 // Move on window.
8665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8666 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8667 ADISPLAY_ID_DEFAULT, {50, 50}))
8668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8669 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8670 mWindow->consumeDragEvent(false, 50, 50);
8671 mSecondWindow->assertNoEvents();
8672
8673 // Move to another window.
8674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8675 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8676 ADISPLAY_ID_DEFAULT, {150, 50}))
8677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8678 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8679 mWindow->consumeDragEvent(true, 150, 50);
8680 mSecondWindow->consumeDragEvent(false, 50, 50);
8681
8682 // drop to another window.
8683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8684 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8685 {150, 50}))
8686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8687 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008688 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008689 mWindow->assertNoEvents();
8690 mSecondWindow->assertNoEvents();
8691}
8692
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008693TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8694 startDrag(true, AINPUT_SOURCE_MOUSE);
8695 // Move on window.
8696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8697 injectMotionEvent(mDispatcher,
8698 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8699 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8700 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008701 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008702 .x(50)
8703 .y(50))
8704 .build()))
8705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8706 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8707 mWindow->consumeDragEvent(false, 50, 50);
8708 mSecondWindow->assertNoEvents();
8709
8710 // Move to another window.
8711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8712 injectMotionEvent(mDispatcher,
8713 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8714 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8715 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008716 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008717 .x(150)
8718 .y(50))
8719 .build()))
8720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8721 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8722 mWindow->consumeDragEvent(true, 150, 50);
8723 mSecondWindow->consumeDragEvent(false, 50, 50);
8724
8725 // drop to another window.
8726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8727 injectMotionEvent(mDispatcher,
8728 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8729 .buttonState(0)
8730 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008731 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008732 .x(150)
8733 .y(50))
8734 .build()))
8735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8736 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008737 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008738 mWindow->assertNoEvents();
8739 mSecondWindow->assertNoEvents();
8740}
8741
Vishnu Nair062a8672021-09-03 16:07:44 -07008742class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8743
8744TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8745 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008746 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8747 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008748 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008749 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8750 window->setFocusable(true);
8751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8752 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008753 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008754
8755 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008756 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008757 window->assertNoEvents();
8758
Prabir Pradhan678438e2023-04-13 19:32:51 +00008759 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8760 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8762 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008763 window->assertNoEvents();
8764
8765 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008766 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008767 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8768
Prabir Pradhan678438e2023-04-13 19:32:51 +00008769 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008770 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8771
Prabir Pradhan678438e2023-04-13 19:32:51 +00008772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8773 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008774 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8775 window->assertNoEvents();
8776}
8777
8778TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8779 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8780 std::make_shared<FakeApplicationHandle>();
8781 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008782 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8783 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008784 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008785 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008786 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8789 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008790 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008791 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008792 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8793 window->setFocusable(true);
8794 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8795 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008796 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008797
8798 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008799 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008800 window->assertNoEvents();
8801
Prabir Pradhan678438e2023-04-13 19:32:51 +00008802 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8803 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008804 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8805 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008806 window->assertNoEvents();
8807
8808 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008809 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8811
Prabir Pradhan678438e2023-04-13 19:32:51 +00008812 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008813 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8814
Prabir Pradhan678438e2023-04-13 19:32:51 +00008815 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8816 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008817 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8818 window->assertNoEvents();
8819}
8820
8821TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8822 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8823 std::make_shared<FakeApplicationHandle>();
8824 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008825 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8826 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008827 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008828 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008829 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008831 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8832 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008833 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008834 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008835 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8836 window->setFocusable(true);
8837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8838 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008839 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008840
8841 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008842 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008843 window->assertNoEvents();
8844
Prabir Pradhan678438e2023-04-13 19:32:51 +00008845 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8846 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008847 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8848 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008849 window->assertNoEvents();
8850
8851 // When the window is no longer obscured because it went on top, it should get input
8852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8853
Prabir Pradhan678438e2023-04-13 19:32:51 +00008854 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008855 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8856
Prabir Pradhan678438e2023-04-13 19:32:51 +00008857 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8858 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008859 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8860 window->assertNoEvents();
8861}
8862
Antonio Kantekf16f2832021-09-28 04:39:20 +00008863class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8864protected:
8865 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008866 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008867 sp<FakeWindowHandle> mWindow;
8868 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008869 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008870
8871 void SetUp() override {
8872 InputDispatcherTest::SetUp();
8873
8874 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008875 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008876 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008877 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008878 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008879 mSecondWindow =
8880 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008881 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008882 mThirdWindow =
8883 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8884 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8885 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008886
8887 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8889 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8890 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008891 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008892
Antonio Kantek15beb512022-06-13 22:35:41 +00008893 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008894 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008895 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008896 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8897 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008898 mThirdWindow->assertNoEvents();
8899 }
8900
8901 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8902 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008903 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008904 SECOND_DISPLAY_ID)) {
8905 mWindow->assertNoEvents();
8906 mSecondWindow->assertNoEvents();
8907 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008908 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008909 }
8910
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008911 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008912 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008913 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8914 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008915 mWindow->consumeTouchModeEvent(inTouchMode);
8916 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008917 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008918 }
8919};
8920
Antonio Kantek26defcf2022-02-08 01:12:27 +00008921TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008922 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008923 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8924 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008925 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008926}
8927
Antonio Kantek26defcf2022-02-08 01:12:27 +00008928TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8929 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008930 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008931 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008932 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008933 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008934 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008935 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008936 mWindow->assertNoEvents();
8937 mSecondWindow->assertNoEvents();
8938}
8939
8940TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8941 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008942 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008943 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008944 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008945 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008946 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008947}
8948
Antonio Kantekf16f2832021-09-28 04:39:20 +00008949TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008950 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008951 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8952 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008953 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008954 mWindow->assertNoEvents();
8955 mSecondWindow->assertNoEvents();
8956}
8957
Antonio Kantek15beb512022-06-13 22:35:41 +00008958TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8959 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8960 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8961 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008962 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008963 mWindow->assertNoEvents();
8964 mSecondWindow->assertNoEvents();
8965 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8966}
8967
Antonio Kantek48710e42022-03-24 14:19:30 -07008968TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8969 // Interact with the window first.
8970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8971 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8972 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8973
8974 // Then remove focus.
8975 mWindow->setFocusable(false);
8976 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8977
8978 // Assert that caller can switch touch mode by owning one of the last interacted window.
8979 const WindowInfo& windowInfo = *mWindow->getInfo();
8980 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8981 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008982 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008983}
8984
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008985class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8986public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008987 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008988 std::shared_ptr<FakeApplicationHandle> application =
8989 std::make_shared<FakeApplicationHandle>();
8990 std::string name = "Fake Spy ";
8991 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008992 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8993 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008994 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008995 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008996 return spy;
8997 }
8998
8999 sp<FakeWindowHandle> createForeground() {
9000 std::shared_ptr<FakeApplicationHandle> application =
9001 std::make_shared<FakeApplicationHandle>();
9002 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009003 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9004 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009005 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009006 return window;
9007 }
9008
9009private:
9010 int mSpyCount{0};
9011};
9012
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009013using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009014/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009015 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9016 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009017TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
9018 ScopedSilentDeath _silentDeath;
9019
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009020 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009021 spy->setTrustedOverlay(false);
9022 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
9023 ".* not a trusted overlay");
9024}
9025
9026/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009027 * Input injection into a display with a spy window but no foreground windows should succeed.
9028 */
9029TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009030 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009031 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9032
9033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9034 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9036 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9037}
9038
9039/**
9040 * Verify the order in which different input windows receive events. The touched foreground window
9041 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9042 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9043 * receive events before ones belows it.
9044 *
9045 * Here, we set up a scenario with four windows in the following Z order from the top:
9046 * spy1, spy2, window, spy3.
9047 * We then inject an event and verify that the foreground "window" receives it first, followed by
9048 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9049 * window.
9050 */
9051TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9052 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009053 auto spy1 = createSpy();
9054 auto spy2 = createSpy();
9055 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009056 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9057 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9058 const size_t numChannels = channels.size();
9059
Michael Wright8e9a8562022-02-09 13:44:29 +00009060 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009061 if (!epollFd.ok()) {
9062 FAIL() << "Failed to create epoll fd";
9063 }
9064
9065 for (size_t i = 0; i < numChannels; i++) {
9066 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9067 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9068 FAIL() << "Failed to add fd to epoll";
9069 }
9070 }
9071
9072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9073 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9075
9076 std::vector<size_t> eventOrder;
9077 std::vector<struct epoll_event> events(numChannels);
9078 for (;;) {
9079 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9080 (100ms).count());
9081 if (nFds < 0) {
9082 FAIL() << "Failed to call epoll_wait";
9083 }
9084 if (nFds == 0) {
9085 break; // epoll_wait timed out
9086 }
9087 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009088 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009089 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009090 channels[i]->consumeMotionDown();
9091 }
9092 }
9093
9094 // Verify the order in which the events were received.
9095 EXPECT_EQ(3u, eventOrder.size());
9096 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9097 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9098 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9099}
9100
9101/**
9102 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9103 */
9104TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9105 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009106 auto spy = createSpy();
9107 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009108 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9109
9110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9111 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9113 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9114 spy->assertNoEvents();
9115}
9116
9117/**
9118 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9119 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9120 * to the window.
9121 */
9122TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9123 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009124 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009125 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9126 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9127
9128 // Inject an event outside the spy window's touchable region.
9129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9130 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9132 window->consumeMotionDown();
9133 spy->assertNoEvents();
9134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9135 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9137 window->consumeMotionUp();
9138 spy->assertNoEvents();
9139
9140 // Inject an event inside the spy window's touchable region.
9141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9142 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9143 {5, 10}))
9144 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9145 window->consumeMotionDown();
9146 spy->consumeMotionDown();
9147}
9148
9149/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009150 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009151 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009152 */
9153TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9154 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009155 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009156 auto spy = createSpy();
9157 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009158 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009159 spy->setFrame(Rect{0, 0, 20, 20});
9160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9161
9162 // Inject an event outside the spy window's frame and touchable region.
9163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009164 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9165 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9167 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009168 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009169}
9170
9171/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009172 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9173 * pointers that are down within its bounds.
9174 */
9175TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9176 auto windowLeft = createForeground();
9177 windowLeft->setFrame({0, 0, 100, 200});
9178 auto windowRight = createForeground();
9179 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009180 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009181 spy->setFrame({0, 0, 200, 200});
9182 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9183
9184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9185 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9186 {50, 50}))
9187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9188 windowLeft->consumeMotionDown();
9189 spy->consumeMotionDown();
9190
9191 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009192 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009193 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9195 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009196 .build();
9197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9198 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9199 InputEventInjectionSync::WAIT_FOR_RESULT))
9200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9201 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009202 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009203}
9204
9205/**
9206 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9207 * the spy should receive the second pointer with ACTION_DOWN.
9208 */
9209TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9210 auto window = createForeground();
9211 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009212 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009213 spyRight->setFrame({100, 0, 200, 200});
9214 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9215
9216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9217 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9218 {50, 50}))
9219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9220 window->consumeMotionDown();
9221 spyRight->assertNoEvents();
9222
9223 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009224 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009225 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009226 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9227 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009228 .build();
9229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9230 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9231 InputEventInjectionSync::WAIT_FOR_RESULT))
9232 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009233 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009234 spyRight->consumeMotionDown();
9235}
9236
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009237/**
9238 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9239 * windows should be allowed to control split touch.
9240 */
9241TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009242 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009243 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009244 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009245 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009246
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009247 auto window = createForeground();
9248 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009249
9250 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9251
9252 // First finger down, no window touched.
9253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9254 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9255 {100, 200}))
9256 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9257 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9258 window->assertNoEvents();
9259
9260 // Second finger down on window, the window should receive touch down.
9261 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009262 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009263 .displayId(ADISPLAY_ID_DEFAULT)
9264 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009265 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9266 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009267 .build();
9268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9269 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9270 InputEventInjectionSync::WAIT_FOR_RESULT))
9271 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9272
9273 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009274 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009275}
9276
9277/**
9278 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9279 * do not receive key events.
9280 */
9281TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009282 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009283 spy->setFocusable(false);
9284
9285 auto window = createForeground();
9286 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9287 setFocusedWindow(window);
9288 window->consumeFocusEvent(true);
9289
9290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9291 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9292 window->consumeKeyDown(ADISPLAY_ID_NONE);
9293
9294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9295 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9296 window->consumeKeyUp(ADISPLAY_ID_NONE);
9297
9298 spy->assertNoEvents();
9299}
9300
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009301using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9302
9303/**
9304 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9305 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9306 */
9307TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9308 auto window = createForeground();
9309 auto spy1 = createSpy();
9310 auto spy2 = createSpy();
9311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9312
9313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9314 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9316 window->consumeMotionDown();
9317 spy1->consumeMotionDown();
9318 spy2->consumeMotionDown();
9319
9320 // Pilfer pointers from the second spy window.
9321 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9322 spy2->assertNoEvents();
9323 spy1->consumeMotionCancel();
9324 window->consumeMotionCancel();
9325
9326 // The rest of the gesture should only be sent to the second spy window.
9327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9328 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9329 ADISPLAY_ID_DEFAULT))
9330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9331 spy2->consumeMotionMove();
9332 spy1->assertNoEvents();
9333 window->assertNoEvents();
9334}
9335
9336/**
9337 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9338 * in the middle of the gesture.
9339 */
9340TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9341 auto window = createForeground();
9342 auto spy = createSpy();
9343 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9344
9345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9346 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9348 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9349 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9350
9351 window->releaseChannel();
9352
9353 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9354
9355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9356 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9358 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9359}
9360
9361/**
9362 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9363 * the spy, but not to any other windows.
9364 */
9365TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9366 auto spy = createSpy();
9367 auto window = createForeground();
9368
9369 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9370
9371 // First finger down on the window and the spy.
9372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9373 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9374 {100, 200}))
9375 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9376 spy->consumeMotionDown();
9377 window->consumeMotionDown();
9378
9379 // Spy window pilfers the pointers.
9380 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9381 window->consumeMotionCancel();
9382
9383 // Second finger down on the window and spy, but the window should not receive the pointer down.
9384 const MotionEvent secondFingerDownEvent =
9385 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9386 .displayId(ADISPLAY_ID_DEFAULT)
9387 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009388 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9389 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009390 .build();
9391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9392 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9393 InputEventInjectionSync::WAIT_FOR_RESULT))
9394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9395
Harry Cutts33476232023-01-30 19:57:29 +00009396 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009397
9398 // Third finger goes down outside all windows, so injection should fail.
9399 const MotionEvent thirdFingerDownEvent =
9400 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9401 .displayId(ADISPLAY_ID_DEFAULT)
9402 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009403 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9404 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9405 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009406 .build();
9407 ASSERT_EQ(InputEventInjectionResult::FAILED,
9408 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9409 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009410 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009411
9412 spy->assertNoEvents();
9413 window->assertNoEvents();
9414}
9415
9416/**
9417 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9418 */
9419TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9420 auto spy = createSpy();
9421 spy->setFrame(Rect(0, 0, 100, 100));
9422 auto window = createForeground();
9423 window->setFrame(Rect(0, 0, 200, 200));
9424
9425 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9426
9427 // First finger down on the window only
9428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9429 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9430 {150, 150}))
9431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9432 window->consumeMotionDown();
9433
9434 // Second finger down on the spy and window
9435 const MotionEvent secondFingerDownEvent =
9436 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9437 .displayId(ADISPLAY_ID_DEFAULT)
9438 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009439 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9440 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009441 .build();
9442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9443 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9444 InputEventInjectionSync::WAIT_FOR_RESULT))
9445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9446 spy->consumeMotionDown();
9447 window->consumeMotionPointerDown(1);
9448
9449 // Third finger down on the spy and window
9450 const MotionEvent thirdFingerDownEvent =
9451 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9452 .displayId(ADISPLAY_ID_DEFAULT)
9453 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009454 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9455 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9456 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009457 .build();
9458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9459 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9460 InputEventInjectionSync::WAIT_FOR_RESULT))
9461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9462 spy->consumeMotionPointerDown(1);
9463 window->consumeMotionPointerDown(2);
9464
9465 // Spy window pilfers the pointers.
9466 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009467 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9468 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009469
9470 spy->assertNoEvents();
9471 window->assertNoEvents();
9472}
9473
9474/**
9475 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9476 * other windows should be canceled. If this results in the cancellation of all pointers for some
9477 * window, then that window should receive ACTION_CANCEL.
9478 */
9479TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9480 auto spy = createSpy();
9481 spy->setFrame(Rect(0, 0, 100, 100));
9482 auto window = createForeground();
9483 window->setFrame(Rect(0, 0, 200, 200));
9484
9485 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9486
9487 // First finger down on both spy and window
9488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9489 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9490 {10, 10}))
9491 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9492 window->consumeMotionDown();
9493 spy->consumeMotionDown();
9494
9495 // Second finger down on the spy and window
9496 const MotionEvent secondFingerDownEvent =
9497 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9498 .displayId(ADISPLAY_ID_DEFAULT)
9499 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009500 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9501 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009502 .build();
9503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9504 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9505 InputEventInjectionSync::WAIT_FOR_RESULT))
9506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9507 spy->consumeMotionPointerDown(1);
9508 window->consumeMotionPointerDown(1);
9509
9510 // Spy window pilfers the pointers.
9511 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9512 window->consumeMotionCancel();
9513
9514 spy->assertNoEvents();
9515 window->assertNoEvents();
9516}
9517
9518/**
9519 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9520 * be sent to other windows
9521 */
9522TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9523 auto spy = createSpy();
9524 spy->setFrame(Rect(0, 0, 100, 100));
9525 auto window = createForeground();
9526 window->setFrame(Rect(0, 0, 200, 200));
9527
9528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9529
9530 // First finger down on both window and spy
9531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9532 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9533 {10, 10}))
9534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9535 window->consumeMotionDown();
9536 spy->consumeMotionDown();
9537
9538 // Spy window pilfers the pointers.
9539 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9540 window->consumeMotionCancel();
9541
9542 // Second finger down on the window only
9543 const MotionEvent secondFingerDownEvent =
9544 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9545 .displayId(ADISPLAY_ID_DEFAULT)
9546 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009547 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9548 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009549 .build();
9550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9551 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9552 InputEventInjectionSync::WAIT_FOR_RESULT))
9553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9554 window->consumeMotionDown();
9555 window->assertNoEvents();
9556
9557 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9558 spy->consumeMotionMove();
9559 spy->assertNoEvents();
9560}
9561
Prabir Pradhand65552b2021-10-07 11:23:50 -07009562class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9563public:
9564 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9565 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9566 std::make_shared<FakeApplicationHandle>();
9567 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009568 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9569 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009570 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009571 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009572 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009573 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009574 overlay->setTrustedOverlay(true);
9575
9576 std::shared_ptr<FakeApplicationHandle> application =
9577 std::make_shared<FakeApplicationHandle>();
9578 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009579 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9580 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009581 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009582 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009583
9584 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9585 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9586 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009587 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009588 return {std::move(overlay), std::move(window)};
9589 }
9590
9591 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009592 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009593 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009594 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009595 }
9596
9597 void sendStylusEvent(int32_t action) {
9598 NotifyMotionArgs motionArgs =
9599 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9600 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009601 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009602 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009603 }
9604};
9605
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009606using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9607
9608TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009609 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009610 ScopedSilentDeath _silentDeath;
9611
Prabir Pradhand65552b2021-10-07 11:23:50 -07009612 auto [overlay, window] = setupStylusOverlayScenario();
9613 overlay->setTrustedOverlay(false);
9614 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9615 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9616 ".* not a trusted overlay");
9617}
9618
9619TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9620 auto [overlay, window] = setupStylusOverlayScenario();
9621 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9622
9623 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9624 overlay->consumeMotionDown();
9625 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9626 overlay->consumeMotionUp();
9627
9628 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9629 window->consumeMotionDown();
9630 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9631 window->consumeMotionUp();
9632
9633 overlay->assertNoEvents();
9634 window->assertNoEvents();
9635}
9636
9637TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9638 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009639 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9641
9642 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9643 overlay->consumeMotionDown();
9644 window->consumeMotionDown();
9645 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9646 overlay->consumeMotionUp();
9647 window->consumeMotionUp();
9648
9649 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9650 window->consumeMotionDown();
9651 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9652 window->consumeMotionUp();
9653
9654 overlay->assertNoEvents();
9655 window->assertNoEvents();
9656}
9657
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009658/**
9659 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9660 * The scenario is as follows:
9661 * - The stylus interceptor overlay is configured as a spy window.
9662 * - The stylus interceptor spy receives the start of a new stylus gesture.
9663 * - It pilfers pointers and then configures itself to no longer be a spy.
9664 * - The stylus interceptor continues to receive the rest of the gesture.
9665 */
9666TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9667 auto [overlay, window] = setupStylusOverlayScenario();
9668 overlay->setSpy(true);
9669 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9670
9671 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9672 overlay->consumeMotionDown();
9673 window->consumeMotionDown();
9674
9675 // The interceptor pilfers the pointers.
9676 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9677 window->consumeMotionCancel();
9678
9679 // The interceptor configures itself so that it is no longer a spy.
9680 overlay->setSpy(false);
9681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9682
9683 // It continues to receive the rest of the stylus gesture.
9684 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9685 overlay->consumeMotionMove();
9686 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9687 overlay->consumeMotionUp();
9688
9689 window->assertNoEvents();
9690}
9691
Prabir Pradhan5735a322022-04-11 17:23:34 +00009692struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009693 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009694 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009695 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9696 std::unique_ptr<InputDispatcher>& mDispatcher;
9697
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009698 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009699 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9700
9701 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9702 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9703 ADISPLAY_ID_DEFAULT, {100, 200},
9704 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9705 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9706 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9707 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9708 }
9709
9710 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009711 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009712 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009713 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009714 mPolicyFlags);
9715 }
9716
9717 sp<FakeWindowHandle> createWindow() const {
9718 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9719 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009720 sp<FakeWindowHandle> window =
9721 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9722 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009723 window->setOwnerInfo(mPid, mUid);
9724 return window;
9725 }
9726};
9727
9728using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9729
9730TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009731 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009732 auto window = owner.createWindow();
9733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9734
9735 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9736 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9737 window->consumeMotionDown();
9738
9739 setFocusedWindow(window);
9740 window->consumeFocusEvent(true);
9741
9742 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9743 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9744 window->consumeKeyDown(ADISPLAY_ID_NONE);
9745}
9746
9747TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009748 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009749 auto window = owner.createWindow();
9750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9751
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009752 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009753 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9754 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9755
9756 setFocusedWindow(window);
9757 window->consumeFocusEvent(true);
9758
9759 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9760 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9761 window->assertNoEvents();
9762}
9763
9764TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009765 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009766 auto window = owner.createWindow();
9767 auto spy = owner.createWindow();
9768 spy->setSpy(true);
9769 spy->setTrustedOverlay(true);
9770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9771
9772 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9773 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9774 spy->consumeMotionDown();
9775 window->consumeMotionDown();
9776}
9777
9778TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009779 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009780 auto window = owner.createWindow();
9781
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009782 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009783 auto randosSpy = rando.createWindow();
9784 randosSpy->setSpy(true);
9785 randosSpy->setTrustedOverlay(true);
9786 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9787
9788 // The event is targeted at owner's window, so injection should succeed, but the spy should
9789 // not receive the event.
9790 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9791 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9792 randosSpy->assertNoEvents();
9793 window->consumeMotionDown();
9794}
9795
9796TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009797 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009798 auto window = owner.createWindow();
9799
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009800 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009801 auto randosSpy = rando.createWindow();
9802 randosSpy->setSpy(true);
9803 randosSpy->setTrustedOverlay(true);
9804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9805
9806 // A user that has injection permission can inject into any window.
9807 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9808 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9809 ADISPLAY_ID_DEFAULT));
9810 randosSpy->consumeMotionDown();
9811 window->consumeMotionDown();
9812
9813 setFocusedWindow(randosSpy);
9814 randosSpy->consumeFocusEvent(true);
9815
9816 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9817 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9818 window->assertNoEvents();
9819}
9820
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009821TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009822 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009823 auto window = owner.createWindow();
9824
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009825 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009826 auto randosWindow = rando.createWindow();
9827 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9828 randosWindow->setWatchOutsideTouch(true);
9829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9830
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009831 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009832 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9833 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9834 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009835 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009836}
9837
Garfield Tane84e6f92019-08-29 17:28:41 -07009838} // namespace android::inputdispatcher