blob: 9544da1d7b34baf0af5b7bddba377db37702a9a8 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Prabir Pradhan9205e422023-05-16 20:06:13 +000019#include "EventBuilders.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070021#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080022#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080023#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070024#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070025#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000026#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080027#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir 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
arthurhungf452d0b2021-01-06 00:19:52 +0800380 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
381 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800382 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800383 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800384 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800385 }
386
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800387 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<sp<IBinder>> receivedToken =
391 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
392 mNotifyInputChannelBroken);
393 ASSERT_TRUE(receivedToken.has_value());
394 ASSERT_EQ(token, *receivedToken);
395 }
396
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800397 /**
398 * Set policy timeout. A value of zero means next key will not be intercepted.
399 */
400 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
401 mInterceptKeyTimeout = timeout;
402 }
403
Josep del Riob3981622023-04-18 15:49:45 +0000404 void assertUserActivityPoked() {
405 std::scoped_lock lock(mLock);
406 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
407 }
408
409 void assertUserActivityNotPoked() {
410 std::scoped_lock lock(mLock);
411 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
412 }
413
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000414 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000415 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
416 }
417
418 void assertNotifyDeviceInteractionWasNotCalled() {
419 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
420 }
421
Michael Wrightd02c5b62014-02-10 15:10:22 -0800422private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700423 std::mutex mLock;
424 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
425 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
426 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
427 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800428
Prabir Pradhan99987712020-11-10 18:43:05 -0800429 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000430
431 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800432
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700433 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700434 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800435 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
436 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700437 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800438 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
439 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700440
arthurhungf452d0b2021-01-06 00:19:52 +0800441 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800442 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000443 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800444
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800445 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
446
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000447 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000448
Prabir Pradhanedd96402022-02-15 01:46:16 -0800449 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
450 // for a specific container to become non-empty. When the container is non-empty, return the
451 // first entry from the container and erase it.
452 template <class T>
453 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
454 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
455 // If there is an ANR, Dispatcher won't be idle because there are still events
456 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
457 // before checking if ANR was called.
458 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
459 // to provide it some time to act. 100ms seems reasonable.
460 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
461 const std::chrono::time_point start = std::chrono::steady_clock::now();
462 std::optional<T> token =
463 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
464 if (!token.has_value()) {
465 ADD_FAILURE() << "Did not receive the ANR callback";
466 return {};
467 }
468
469 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
470 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
471 // the dispatcher started counting before this function was called
472 if (std::chrono::abs(timeout - waited) > 100ms) {
473 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
474 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
475 << "ms, but waited "
476 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
477 << "ms instead";
478 }
479 return *token;
480 }
481
482 template <class T>
483 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
484 std::queue<T>& storage,
485 std::unique_lock<std::mutex>& lock,
486 std::condition_variable& condition)
487 REQUIRES(mLock) {
488 condition.wait_for(lock, timeout,
489 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
490 if (storage.empty()) {
491 ADD_FAILURE() << "Did not receive the expected callback";
492 return std::nullopt;
493 }
494 T item = storage.front();
495 storage.pop();
496 return std::make_optional(item);
497 }
498
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600499 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700500 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800501 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800502 }
503
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000504 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800505 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700506 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800507 ASSERT_TRUE(pid.has_value());
508 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700509 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500510 }
511
Prabir Pradhanedd96402022-02-15 01:46:16 -0800512 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000513 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500514 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800515 ASSERT_TRUE(pid.has_value());
516 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500517 mNotifyAnr.notify_all();
518 }
519
520 void notifyNoFocusedWindowAnr(
521 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
522 std::scoped_lock lock(mLock);
523 mAnrApplications.push(applicationHandle);
524 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525 }
526
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800527 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
528 std::scoped_lock lock(mLock);
529 mBrokenInputChannels.push(connectionToken);
530 mNotifyInputChannelBroken.notify_all();
531 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800532
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600533 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700534
Chris Yef59a2f42020-10-16 12:55:26 -0700535 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
536 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
537 const std::vector<float>& values) override {}
538
539 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
540 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000541
Chris Yefb552902021-02-03 17:18:37 -0800542 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
543
Prabir Pradhana41d2442023-04-20 21:30:40 +0000544 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700545 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000546 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700547 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000548 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
549 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800550 break;
551 }
552
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700553 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
555 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800556 break;
557 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700558 default: {
559 ADD_FAILURE() << "Should only filter keys or motions";
560 break;
561 }
Jackal Guof9696682018-10-05 12:23:23 +0800562 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 return true;
564 }
565
Prabir Pradhana41d2442023-04-20 21:30:40 +0000566 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
567 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800568 // Clear intercept state when we handled the event.
569 mInterceptKeyTimeout = 0ms;
570 }
571 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800572
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600573 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574
Prabir Pradhana41d2442023-04-20 21:30:40 +0000575 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800576 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
577 // Clear intercept state so we could dispatch the event in next wake.
578 mInterceptKeyTimeout = 0ms;
579 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580 }
581
Prabir Pradhana41d2442023-04-20 21:30:40 +0000582 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
583 uint32_t) override {
584 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585 }
586
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600587 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
588 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800590 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
591 * essentially a passthrough for notifySwitch.
592 */
Harry Cutts33476232023-01-30 19:57:29 +0000593 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594 }
595
Josep del Riob3981622023-04-18 15:49:45 +0000596 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
597 std::scoped_lock lock(mLock);
598 mPokedUserActivity = true;
599 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800600
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600601 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700602 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700603 mOnPointerDownToken = newToken;
604 }
605
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000606 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800607 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000608 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800609 mPointerCaptureChangedCondition.notify_all();
610 }
611
arthurhungf452d0b2021-01-06 00:19:52 +0800612 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
613 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800614 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800615 mDropTargetWindowToken = token;
616 }
617
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000618 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000619 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000620 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
621 }
622
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700623 void assertFilterInputEventWasCalledInternal(
624 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700625 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800626 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700627 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800628 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800629 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800630};
631
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632// --- InputDispatcherTest ---
633
634class InputDispatcherTest : public testing::Test {
635protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000636 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700637 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800638
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000639 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000640 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
641 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800642 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000643 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700644 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800645 }
646
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000647 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700648 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000649 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700650 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800651 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700652
653 /**
654 * Used for debugging when writing the test
655 */
656 void dumpDispatcherState() {
657 std::string dump;
658 mDispatcher->dump(dump);
659 std::stringstream ss(dump);
660 std::string to;
661
662 while (std::getline(ss, to, '\n')) {
663 ALOGE("%s", to.c_str());
664 }
665 }
Vishnu Nair958da932020-08-21 17:12:37 -0700666
Chavi Weingarten847e8512023-03-29 00:26:09 +0000667 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700668 FocusRequest request;
669 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000670 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700671 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
672 request.displayId = window->getInfo()->displayId;
673 mDispatcher->setFocusedWindow(request);
674 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800675};
676
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
678 KeyEvent event;
679
680 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800681 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
682 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600683 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
684 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800685 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000686 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000687 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800688 << "Should reject key events with undefined action.";
689
690 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800691 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
692 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600693 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800694 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000695 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000696 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800697 << "Should reject key events with ACTION_MULTIPLE.";
698}
699
700TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
701 MotionEvent event;
702 PointerProperties pointerProperties[MAX_POINTERS + 1];
703 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800704 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705 pointerProperties[i].clear();
706 pointerProperties[i].id = i;
707 pointerCoords[i].clear();
708 }
709
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800710 // Some constants commonly used below
711 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
712 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
713 constexpr int32_t metaState = AMETA_NONE;
714 constexpr MotionClassification classification = MotionClassification::NONE;
715
chaviw9eaa22c2020-07-01 16:21:27 -0700716 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800717 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800718 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700719 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
720 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700721 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
722 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700723 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000725 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject motion events with undefined action.";
728
729 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800731 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
732 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
733 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
734 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500735 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000737 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000738 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800739 << "Should reject motion events with pointer down index too large.";
740
Garfield Tanfbe732e2020-01-24 11:26:14 -0800741 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700742 AMOTION_EVENT_ACTION_POINTER_DOWN |
743 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700744 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
745 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700746 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500747 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800748 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000749 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000750 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800751 << "Should reject motion events with pointer down index too small.";
752
753 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800755 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
756 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
757 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
758 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500759 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000761 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000762 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763 << "Should reject motion events with pointer up index too large.";
764
Garfield Tanfbe732e2020-01-24 11:26:14 -0800765 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700766 AMOTION_EVENT_ACTION_POINTER_UP |
767 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700768 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
769 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500771 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800772 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000773 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000774 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800775 << "Should reject motion events with pointer up index too small.";
776
777 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700783 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with 0 pointers.";
788
Garfield Tanfbe732e2020-01-24 11:26:14 -0800789 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
790 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700791 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700792 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
793 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800795 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000796 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000797 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798 << "Should reject motion events with more than MAX_POINTERS pointers.";
799
800 // Rejects motion events with invalid pointer ids.
801 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800802 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
803 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700804 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700805 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
806 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700807 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800808 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000809 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000810 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800811 << "Should reject motion events with pointer ids less than 0.";
812
813 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800814 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
815 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700816 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700817 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
818 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700819 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800820 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000821 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000822 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800823 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
824
825 // Rejects motion events with duplicate pointer ids.
826 pointerProperties[0].id = 1;
827 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800828 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
829 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700830 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700831 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
832 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700833 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800834 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000835 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000836 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800837 << "Should reject motion events with duplicate pointer ids.";
838}
839
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800840/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
841
842TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
843 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000844 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800845 ASSERT_TRUE(mDispatcher->waitForIdle());
846
847 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
848}
849
850TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000851 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
852 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000853 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800854
855 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
856 args.policyFlags |= POLICY_FLAG_TRUSTED;
857 mFakePolicy->assertNotifySwitchWasCalled(args);
858}
859
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700860namespace {
861
Arthur Hungb92218b2018-08-14 12:00:21 +0800862// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700863static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700864// Default input dispatching timeout if there is no focused application or paused window
865// from which to determine an appropriate dispatching timeout.
866static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
867 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
868 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800869
870class FakeApplicationHandle : public InputApplicationHandle {
871public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700872 FakeApplicationHandle() {
873 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700874 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500875 mInfo.dispatchingTimeoutMillis =
876 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700877 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800878 virtual ~FakeApplicationHandle() {}
879
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000880 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500882 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
883 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800885};
886
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800887class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800888public:
Garfield Tan15601662020-09-22 15:32:38 -0700889 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800890 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700891 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800892 }
893
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800894 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700895 InputEvent* event;
896 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
897 if (!consumeSeq) {
898 return nullptr;
899 }
900 finishEvent(*consumeSeq);
901 return event;
902 }
903
904 /**
905 * Receive an event without acknowledging it.
906 * Return the sequence number that could later be used to send finished signal.
907 */
908 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800909 uint32_t consumeSeq;
910 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800911
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800912 std::chrono::time_point start = std::chrono::steady_clock::now();
913 status_t status = WOULD_BLOCK;
914 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000915 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800916 &event);
917 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
918 if (elapsed > 100ms) {
919 break;
920 }
921 }
922
923 if (status == WOULD_BLOCK) {
924 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700925 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800926 }
927
928 if (status != OK) {
929 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700930 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800931 }
932 if (event == nullptr) {
933 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700934 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800935 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700936 if (outEvent != nullptr) {
937 *outEvent = event;
938 }
939 return consumeSeq;
940 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800941
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700942 /**
943 * To be used together with "receiveEvent" to complete the consumption of an event.
944 */
945 void finishEvent(uint32_t consumeSeq) {
946 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
947 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800948 }
949
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000950 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
951 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
952 ASSERT_EQ(OK, status);
953 }
954
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700955 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000956 std::optional<int32_t> expectedDisplayId,
957 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800958 InputEvent* event = consume();
959
960 ASSERT_NE(nullptr, event) << mName.c_str()
961 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800962 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700963 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
964 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800965
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000966 if (expectedDisplayId.has_value()) {
967 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
968 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800969
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700971 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800972 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
973 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000974 if (expectedFlags.has_value()) {
975 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
976 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800977 break;
978 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700979 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800980 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000981 assertMotionAction(expectedAction, motionEvent.getAction());
982
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000983 if (expectedFlags.has_value()) {
984 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986 break;
987 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100989 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
990 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700991 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800992 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
993 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700994 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000995 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
996 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800998 FAIL() << "Use 'consumeDragEvent' for DRAG events";
999 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001000 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001001 }
1002
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001003 MotionEvent* consumeMotion() {
1004 InputEvent* event = consume();
1005
1006 if (event == nullptr) {
1007 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1008 return nullptr;
1009 }
1010
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001011 if (event->getType() != InputEventType::MOTION) {
1012 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001013 return nullptr;
1014 }
1015 return static_cast<MotionEvent*>(event);
1016 }
1017
1018 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1019 MotionEvent* motionEvent = consumeMotion();
1020 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1021 ASSERT_THAT(*motionEvent, matcher);
1022 }
1023
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001024 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1025 InputEvent* event = consume();
1026 ASSERT_NE(nullptr, event) << mName.c_str()
1027 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001028 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1029 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001030
1031 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1032 << mName.c_str() << ": event displayId should always be NONE.";
1033
1034 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1035 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001036 }
1037
Prabir Pradhan99987712020-11-10 18:43:05 -08001038 void consumeCaptureEvent(bool hasCapture) {
1039 const InputEvent* event = consume();
1040 ASSERT_NE(nullptr, event) << mName.c_str()
1041 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001042 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1043 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001044
1045 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1046 << mName.c_str() << ": event displayId should always be NONE.";
1047
1048 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1049 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1050 }
1051
arthurhungb89ccb02020-12-30 16:19:01 +08001052 void consumeDragEvent(bool isExiting, float x, float y) {
1053 const InputEvent* event = consume();
1054 ASSERT_NE(nullptr, event) << mName.c_str()
1055 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001056 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001057
1058 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1059 << mName.c_str() << ": event displayId should always be NONE.";
1060
1061 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1062 EXPECT_EQ(isExiting, dragEvent.isExiting());
1063 EXPECT_EQ(x, dragEvent.getX());
1064 EXPECT_EQ(y, dragEvent.getY());
1065 }
1066
Antonio Kantekf16f2832021-09-28 04:39:20 +00001067 void consumeTouchModeEvent(bool inTouchMode) {
1068 const InputEvent* event = consume();
1069 ASSERT_NE(nullptr, event) << mName.c_str()
1070 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001071 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1072 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001073
1074 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1075 << mName.c_str() << ": event displayId should always be NONE.";
1076 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1077 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1078 }
1079
chaviwd1c23182019-12-20 18:44:56 -08001080 void assertNoEvents() {
1081 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001082 if (event == nullptr) {
1083 return;
1084 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001085 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001086 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1087 ADD_FAILURE() << "Received key event "
1088 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001089 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001090 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1091 ADD_FAILURE() << "Received motion event "
1092 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001093 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1095 ADD_FAILURE() << "Received focus event, hasFocus = "
1096 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001097 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001098 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1099 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1100 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001102 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1103 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1104 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001105 }
1106 FAIL() << mName.c_str()
1107 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001108 }
1109
1110 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1111
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001112 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1113
chaviwd1c23182019-12-20 18:44:56 -08001114protected:
1115 std::unique_ptr<InputConsumer> mConsumer;
1116 PreallocatedInputEventFactory mEventFactory;
1117
1118 std::string mName;
1119};
1120
chaviw3277faf2021-05-19 16:45:23 -05001121class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001122public:
1123 static const int32_t WIDTH = 600;
1124 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001125
Chris Yea209fde2020-07-22 13:54:51 -07001126 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001127 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001128 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001129 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001130 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001131 base::Result<std::unique_ptr<InputChannel>> channel =
1132 dispatcher->createInputChannel(name);
1133 token = (*channel)->getConnectionToken();
1134 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001135 }
1136
1137 inputApplicationHandle->updateInfo();
1138 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1139
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001140 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001141 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001142 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001143 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001144 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001145 mInfo.frameLeft = 0;
1146 mInfo.frameTop = 0;
1147 mInfo.frameRight = WIDTH;
1148 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001149 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001150 mInfo.globalScaleFactor = 1.0;
1151 mInfo.touchableRegion.clear();
1152 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001153 mInfo.ownerPid = WINDOW_PID;
1154 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001155 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001156 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001157 }
1158
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001159 sp<FakeWindowHandle> clone(int32_t displayId) {
1160 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1161 handle->mInfo = mInfo;
1162 handle->mInfo.displayId = displayId;
1163 handle->mInfo.id = sId++;
1164 handle->mInputReceiver = mInputReceiver;
1165 return handle;
1166 }
1167
1168 /**
1169 * This is different from clone, because clone will make a "mirror" window - a window with the
1170 * same token, but a different ID. The original window and the clone window are allowed to be
1171 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1172 * This function will create a different object of WindowInfoHandle, but with the same
1173 * properties as the original object - including the ID.
1174 * You can use either the old or the new object to consume the events.
1175 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1176 * at the same time inside dispatcher.
1177 */
1178 sp<FakeWindowHandle> duplicate() {
1179 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1180 handle->mInfo = mInfo;
1181 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001182 return handle;
1183 }
1184
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001185 void setTouchable(bool touchable) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1187 }
chaviwd1c23182019-12-20 18:44:56 -08001188
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001189 void setFocusable(bool focusable) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1191 }
1192
1193 void setVisible(bool visible) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1195 }
Vishnu Nair958da932020-08-21 17:12:37 -07001196
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001197 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001198 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001199 }
1200
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001201 void setPaused(bool paused) {
1202 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1203 }
1204
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001205 void setPreventSplitting(bool preventSplitting) {
1206 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001207 }
1208
1209 void setSlippery(bool slippery) {
1210 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1211 }
1212
1213 void setWatchOutsideTouch(bool watchOutside) {
1214 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1215 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001216
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001217 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1218
1219 void setInterceptsStylus(bool interceptsStylus) {
1220 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1221 }
1222
1223 void setDropInput(bool dropInput) {
1224 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1225 }
1226
1227 void setDropInputIfObscured(bool dropInputIfObscured) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1229 }
1230
1231 void setNoInputChannel(bool noInputChannel) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1233 }
1234
Josep del Riob3981622023-04-18 15:49:45 +00001235 void setDisableUserActivity(bool disableUserActivity) {
1236 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1237 }
1238
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001239 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1240
chaviw3277faf2021-05-19 16:45:23 -05001241 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001242
Bernardo Rufino7393d172021-02-26 13:56:11 +00001243 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1244
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001245 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001246 mInfo.frameLeft = frame.left;
1247 mInfo.frameTop = frame.top;
1248 mInfo.frameRight = frame.right;
1249 mInfo.frameBottom = frame.bottom;
1250 mInfo.touchableRegion.clear();
1251 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001252
1253 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1254 ui::Transform translate;
1255 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1256 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001257 }
1258
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001259 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1260
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001261 void setIsWallpaper(bool isWallpaper) {
1262 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1263 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001264
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001265 void setDupTouchToWallpaper(bool hasWallpaper) {
1266 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1267 }
chaviwd1c23182019-12-20 18:44:56 -08001268
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001269 void setTrustedOverlay(bool trustedOverlay) {
1270 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1271 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001272
chaviw9eaa22c2020-07-01 16:21:27 -07001273 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1274 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1275 }
1276
1277 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001278
yunho.shinf4a80b82020-11-16 21:13:57 +09001279 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1280
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001281 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001282 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001283 }
1284
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001285 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001286 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001287 }
1288
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001290 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001291 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1292 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001293 }
1294
1295 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001296 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001297 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1298 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001299 }
1300
1301 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001302 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001303 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1304 }
1305
1306 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1307 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001308 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001309 expectedFlags);
1310 }
1311
Svet Ganov5d3bc372020-01-26 23:11:07 -08001312 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001313 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1314 int32_t expectedFlags = 0) {
1315 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1316 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001317 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001318 }
1319
1320 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001321 int32_t expectedFlags = 0) {
1322 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1323 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001324 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001325 }
1326
1327 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001328 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001329 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001330 expectedFlags);
1331 }
1332
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001333 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1334 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001335 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001336 expectedFlags);
1337 }
1338
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001339 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1340 int32_t expectedFlags = 0) {
1341 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001342 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001343 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001344 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1345 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1346 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1347 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1348 }
1349
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001350 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1351 ASSERT_NE(mInputReceiver, nullptr)
1352 << "Cannot consume events from a window with no receiver";
1353 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1354 }
1355
Prabir Pradhan99987712020-11-10 18:43:05 -08001356 void consumeCaptureEvent(bool hasCapture) {
1357 ASSERT_NE(mInputReceiver, nullptr)
1358 << "Cannot consume events from a window with no receiver";
1359 mInputReceiver->consumeCaptureEvent(hasCapture);
1360 }
1361
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001362 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1363 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001364 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001365 ASSERT_THAT(*motionEvent, matcher);
1366 }
1367
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001368 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001369 std::optional<int32_t> expectedDisplayId,
1370 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001371 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1372 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1373 expectedFlags);
1374 }
1375
arthurhungb89ccb02020-12-30 16:19:01 +08001376 void consumeDragEvent(bool isExiting, float x, float y) {
1377 mInputReceiver->consumeDragEvent(isExiting, x, y);
1378 }
1379
Antonio Kantekf16f2832021-09-28 04:39:20 +00001380 void consumeTouchModeEvent(bool inTouchMode) {
1381 ASSERT_NE(mInputReceiver, nullptr)
1382 << "Cannot consume events from a window with no receiver";
1383 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1384 }
1385
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001386 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001387 if (mInputReceiver == nullptr) {
1388 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1389 return std::nullopt;
1390 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001391 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001392 }
1393
1394 void finishEvent(uint32_t sequenceNum) {
1395 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1396 mInputReceiver->finishEvent(sequenceNum);
1397 }
1398
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001399 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1400 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1401 mInputReceiver->sendTimeline(inputEventId, timeline);
1402 }
1403
chaviwaf87b3e2019-10-01 16:59:28 -07001404 InputEvent* consume() {
1405 if (mInputReceiver == nullptr) {
1406 return nullptr;
1407 }
1408 return mInputReceiver->consume();
1409 }
1410
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001411 MotionEvent* consumeMotion() {
1412 InputEvent* event = consume();
1413 if (event == nullptr) {
1414 ADD_FAILURE() << "Consume failed : no event";
1415 return nullptr;
1416 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001417 if (event->getType() != InputEventType::MOTION) {
1418 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001419 return nullptr;
1420 }
1421 return static_cast<MotionEvent*>(event);
1422 }
1423
Arthur Hungb92218b2018-08-14 12:00:21 +08001424 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001425 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001426 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001427 return; // Can't receive events if the window does not have input channel
1428 }
1429 ASSERT_NE(nullptr, mInputReceiver)
1430 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001431 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001432 }
1433
chaviwaf87b3e2019-10-01 16:59:28 -07001434 sp<IBinder> getToken() { return mInfo.token; }
1435
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001436 const std::string& getName() { return mName; }
1437
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001438 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001439 mInfo.ownerPid = ownerPid;
1440 mInfo.ownerUid = ownerUid;
1441 }
1442
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001443 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001444
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001445 void destroyReceiver() { mInputReceiver = nullptr; }
1446
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001447 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1448
chaviwd1c23182019-12-20 18:44:56 -08001449private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001450 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001451 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001452 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001453 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001454 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001455};
1456
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001457std::atomic<int32_t> FakeWindowHandle::sId{1};
1458
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001459static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001460 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001461 int32_t displayId = ADISPLAY_ID_NONE,
1462 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001463 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001464 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001465 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001466 KeyEvent event;
1467 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1468
1469 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001470 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001471 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1472 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001473
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001474 if (!allowKeyRepeat) {
1475 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1476 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001477 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001478 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001479}
1480
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001481static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001482 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001483 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001484}
1485
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001486// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1487// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1488// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001489static InputEventInjectionResult injectKeyDownNoRepeat(
1490 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001491 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001492 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001493 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001494}
1495
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001496static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001497 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001498 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001499}
1500
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001502 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001503 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001504 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001505 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001506 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1507 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001508}
1509
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001510static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001511 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001512 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001513 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001514 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1515 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001516 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001517 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001518 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001519 MotionEventBuilder motionBuilder =
1520 MotionEventBuilder(action, source)
1521 .displayId(displayId)
1522 .eventTime(eventTime)
1523 .rawXCursorPosition(cursorPosition.x)
1524 .rawYCursorPosition(cursorPosition.y)
1525 .pointer(
1526 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1527 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1528 motionBuilder.downTime(eventTime);
1529 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001530
1531 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001532 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1533 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001534}
1535
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001536static InputEventInjectionResult injectMotionDown(
1537 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1538 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001539 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001540}
1541
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001542static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001543 int32_t source, int32_t displayId,
1544 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001545 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001546}
1547
Jackal Guof9696682018-10-05 12:23:23 +08001548static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1549 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1550 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001551 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001552 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1553 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001554
1555 return args;
1556}
1557
Josep del Riob3981622023-04-18 15:49:45 +00001558static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1559 int32_t displayId = ADISPLAY_ID_NONE) {
1560 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1561 // Define a valid key event.
1562 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1563 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1564 currentTime);
1565
1566 return args;
1567}
1568
1569static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1570 int32_t displayId = ADISPLAY_ID_NONE) {
1571 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1572 // Define a valid key event.
1573 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1574 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1575 AMETA_NONE, currentTime);
1576
1577 return args;
1578}
1579
Prabir Pradhan678438e2023-04-13 19:32:51 +00001580[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1581 int32_t displayId,
1582 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001583 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001584 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1585 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1586 }
1587
chaviwd1c23182019-12-20 18:44:56 -08001588 PointerProperties pointerProperties[pointerCount];
1589 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001590
chaviwd1c23182019-12-20 18:44:56 -08001591 for (size_t i = 0; i < pointerCount; i++) {
1592 pointerProperties[i].clear();
1593 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001594 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001595
chaviwd1c23182019-12-20 18:44:56 -08001596 pointerCoords[i].clear();
1597 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1598 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1599 }
Jackal Guof9696682018-10-05 12:23:23 +08001600
1601 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1602 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001603 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001604 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1605 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001606 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1607 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001608 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1609 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001610
1611 return args;
1612}
1613
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001614static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1615 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1616}
1617
chaviwd1c23182019-12-20 18:44:56 -08001618static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1619 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1620}
1621
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001622static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1623 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001624 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001625}
1626
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001627} // namespace
1628
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001629/**
1630 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1631 * broken channel.
1632 */
1633TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1635 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001636 sp<FakeWindowHandle>::make(application, mDispatcher,
1637 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001638
1639 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1640
1641 // Window closes its channel, but the window remains.
1642 window->destroyReceiver();
1643 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1644}
1645
Arthur Hungb92218b2018-08-14 12:00:21 +08001646TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001648 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1649 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001650
Arthur Hung72d8dc32020-03-28 00:48:39 +00001651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1653 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001655
1656 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001657 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001658}
1659
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001660TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001662 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1663 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001664
1665 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1666 // Inject a MotionEvent to an unknown display.
1667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1668 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1670
1671 // Window should receive motion event.
1672 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1673}
1674
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001675/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001676 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677 * This test serves as a sanity check for the next test, where setInputWindows is
1678 * called twice.
1679 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001680TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001681 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001682 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1683 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001684 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001685
1686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1689 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001691
1692 // Window should receive motion event.
1693 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1694}
1695
1696/**
1697 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001698 */
1699TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001701 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1702 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001703 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001704
1705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1706 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1709 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001711
1712 // Window should receive motion event.
1713 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1714}
1715
Arthur Hungb92218b2018-08-14 12:00:21 +08001716// The foreground window should receive the first touch down event.
1717TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001719 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001720 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001721 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001722 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001723
Arthur Hung72d8dc32020-03-28 00:48:39 +00001724 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1726 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001728
1729 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001730 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001731 windowSecond->assertNoEvents();
1732}
1733
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001734/**
1735 * Two windows: A top window, and a wallpaper behind the window.
1736 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1737 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001738 * 1. foregroundWindow <-- dup touch to wallpaper
1739 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001740 */
1741TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1743 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001744 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001745 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001746 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001747 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001748 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001749
1750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1752 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1753 {100, 200}))
1754 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1755
1756 // Both foreground window and its wallpaper should receive the touch down
1757 foregroundWindow->consumeMotionDown();
1758 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1759
1760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1761 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1762 ADISPLAY_ID_DEFAULT, {110, 200}))
1763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1764
1765 foregroundWindow->consumeMotionMove();
1766 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1767
1768 // Now the foreground window goes away, but the wallpaper stays
1769 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1770 foregroundWindow->consumeMotionCancel();
1771 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1772 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1773}
1774
1775/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001776 * Two fingers down on the window, and lift off the first finger.
1777 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1778 * contains a single pointer.
1779 */
1780TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1782 sp<FakeWindowHandle> window =
1783 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1784
1785 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001786 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1788 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1789 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001790 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001791 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1792 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1793 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1794 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001795 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001796 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1797 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1798 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1799 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1801 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1802 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1803
1804 // Remove the window. The gesture should be canceled
1805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1806 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1807 window->consumeMotionEvent(
1808 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1809}
1810
1811/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001812 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1813 * with the following differences:
1814 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1815 * clean up the connection.
1816 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1817 * Ensure that there's no crash in the dispatcher.
1818 */
1819TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1821 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001822 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001823 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001824 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001825 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001826 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001827
1828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1830 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1831 {100, 200}))
1832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1833
1834 // Both foreground window and its wallpaper should receive the touch down
1835 foregroundWindow->consumeMotionDown();
1836 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1837
1838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1839 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1840 ADISPLAY_ID_DEFAULT, {110, 200}))
1841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1842
1843 foregroundWindow->consumeMotionMove();
1844 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1845
1846 // Wallpaper closes its channel, but the window remains.
1847 wallpaperWindow->destroyReceiver();
1848 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1849
1850 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1851 // is no longer valid.
1852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1853 foregroundWindow->consumeMotionCancel();
1854}
1855
Arthur Hungc539dbb2022-12-08 07:45:36 +00001856class ShouldSplitTouchFixture : public InputDispatcherTest,
1857 public ::testing::WithParamInterface<bool> {};
1858INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1859 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001860/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001861 * A single window that receives touch (on top), and a wallpaper window underneath it.
1862 * The top window gets a multitouch gesture.
1863 * Ensure that wallpaper gets the same gesture.
1864 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001865TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001867 sp<FakeWindowHandle> foregroundWindow =
1868 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1869 foregroundWindow->setDupTouchToWallpaper(true);
1870 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001871
1872 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001873 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001874 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001875
Arthur Hungc539dbb2022-12-08 07:45:36 +00001876 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877
1878 // Touch down on top window
1879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1880 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1881 {100, 100}))
1882 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1883
1884 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001885 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001886 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1887
1888 // Second finger down on the top window
1889 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001890 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001892 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1893 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001894 .build();
1895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1896 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1897 InputEventInjectionSync::WAIT_FOR_RESULT))
1898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1899
Harry Cutts33476232023-01-30 19:57:29 +00001900 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1901 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001903
1904 const MotionEvent secondFingerUpEvent =
1905 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1906 .displayId(ADISPLAY_ID_DEFAULT)
1907 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001908 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1909 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001910 .build();
1911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1912 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1913 InputEventInjectionSync::WAIT_FOR_RESULT))
1914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1915 foregroundWindow->consumeMotionPointerUp(0);
1916 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1917
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001919 injectMotionEvent(mDispatcher,
1920 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1921 AINPUT_SOURCE_TOUCHSCREEN)
1922 .displayId(ADISPLAY_ID_DEFAULT)
1923 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1924 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001925 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001926 .x(100)
1927 .y(100))
1928 .build(),
1929 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1931 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1932 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933}
1934
1935/**
1936 * Two windows: a window on the left and window on the right.
1937 * A third window, wallpaper, is behind both windows, and spans both top windows.
1938 * The first touch down goes to the left window. A second pointer touches down on the right window.
1939 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1940 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1941 * ACTION_POINTER_DOWN(1).
1942 */
1943TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1945 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001946 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001948 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001949
1950 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001951 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001953 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001954
1955 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001956 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001958 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001959
1960 mDispatcher->setInputWindows(
1961 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1962
1963 // Touch down on left window
1964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1965 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1966 {100, 100}))
1967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1968
1969 // Both foreground window and its wallpaper should receive the touch down
1970 leftWindow->consumeMotionDown();
1971 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1972
1973 // Second finger down on the right window
1974 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001975 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001977 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1978 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979 .build();
1980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1981 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1982 InputEventInjectionSync::WAIT_FOR_RESULT))
1983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1984
1985 leftWindow->consumeMotionMove();
1986 // Since the touch is split, right window gets ACTION_DOWN
1987 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001988 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989 expectedWallpaperFlags);
1990
1991 // Now, leftWindow, which received the first finger, disappears.
1992 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1993 leftWindow->consumeMotionCancel();
1994 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1995 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1996
1997 // The pointer that's still down on the right window moves, and goes to the right window only.
1998 // As far as the dispatcher's concerned though, both pointers are still present.
1999 const MotionEvent secondFingerMoveEvent =
2000 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2001 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002002 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2003 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 .build();
2005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2006 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2007 InputEventInjectionSync::WAIT_FOR_RESULT));
2008 rightWindow->consumeMotionMove();
2009
2010 leftWindow->assertNoEvents();
2011 rightWindow->assertNoEvents();
2012 wallpaperWindow->assertNoEvents();
2013}
2014
Arthur Hungc539dbb2022-12-08 07:45:36 +00002015/**
2016 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2017 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2018 * The right window should receive ACTION_DOWN.
2019 */
2020TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002021 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002022 sp<FakeWindowHandle> leftWindow =
2023 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2024 leftWindow->setFrame(Rect(0, 0, 200, 200));
2025 leftWindow->setDupTouchToWallpaper(true);
2026 leftWindow->setSlippery(true);
2027
2028 sp<FakeWindowHandle> rightWindow =
2029 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2030 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002031
2032 sp<FakeWindowHandle> wallpaperWindow =
2033 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2034 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002035
Arthur Hungc539dbb2022-12-08 07:45:36 +00002036 mDispatcher->setInputWindows(
2037 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002038
Arthur Hungc539dbb2022-12-08 07:45:36 +00002039 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2041 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002042 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002044
2045 // Both foreground window and its wallpaper should receive the touch down
2046 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002047 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2048
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002051 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2052 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2054
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055 leftWindow->consumeMotionCancel();
2056 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2057 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002058}
2059
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002060/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002061 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2062 * interactive, it might stop sending this flag.
2063 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2064 * to have a consistent input stream.
2065 *
2066 * Test procedure:
2067 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2068 * DOWN (new gesture).
2069 *
2070 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2071 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2072 *
2073 * We technically just need a single window here, but we are using two windows (spy on top and a
2074 * regular window below) to emulate the actual situation where it happens on the device.
2075 */
2076TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2078 sp<FakeWindowHandle> spyWindow =
2079 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2080 spyWindow->setFrame(Rect(0, 0, 200, 200));
2081 spyWindow->setTrustedOverlay(true);
2082 spyWindow->setSpy(true);
2083
2084 sp<FakeWindowHandle> window =
2085 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2086 window->setFrame(Rect(0, 0, 200, 200));
2087
2088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2089 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002090
2091 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002092 mDispatcher->notifyMotion(
2093 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2094 .deviceId(touchDeviceId)
2095 .policyFlags(DEFAULT_POLICY_FLAGS)
2096 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2097 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002098
Prabir Pradhan678438e2023-04-13 19:32:51 +00002099 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2100 .deviceId(touchDeviceId)
2101 .policyFlags(DEFAULT_POLICY_FLAGS)
2102 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2103 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2104 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002105 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2106 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2107 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2108 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2109
2110 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002111 mDispatcher->notifyMotion(
2112 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2113 .deviceId(touchDeviceId)
2114 .policyFlags(0)
2115 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2116 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2117 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002118 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2119 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2120
2121 // We don't need to reset the device to reproduce the issue, but the reset event typically
2122 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002123 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002124
2125 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002126 mDispatcher->notifyMotion(
2127 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2128 .deviceId(touchDeviceId)
2129 .policyFlags(DEFAULT_POLICY_FLAGS)
2130 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2131 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002132 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2133 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2134
2135 // No more events
2136 spyWindow->assertNoEvents();
2137 window->assertNoEvents();
2138}
2139
2140/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002141 * Two windows: a window on the left and a window on the right.
2142 * Mouse is hovered from the right window into the left window.
2143 * Next, we tap on the left window, where the cursor was last seen.
2144 * The second tap is done onto the right window.
2145 * The mouse and tap are from two different devices.
2146 * We technically don't need to set the downtime / eventtime for these events, but setting these
2147 * explicitly helps during debugging.
2148 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2149 * In the buggy implementation, a tap on the right window would cause a crash.
2150 */
2151TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2152 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2153 sp<FakeWindowHandle> leftWindow =
2154 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2155 leftWindow->setFrame(Rect(0, 0, 200, 200));
2156
2157 sp<FakeWindowHandle> rightWindow =
2158 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2159 rightWindow->setFrame(Rect(200, 0, 400, 200));
2160
2161 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2162 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2163 // stale.
2164 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2165 const int32_t mouseDeviceId = 6;
2166 const int32_t touchDeviceId = 4;
2167 // Move the cursor from right
2168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2169 injectMotionEvent(mDispatcher,
2170 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2171 AINPUT_SOURCE_MOUSE)
2172 .deviceId(mouseDeviceId)
2173 .downTime(baseTime + 10)
2174 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002175 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002176 .x(300)
2177 .y(100))
2178 .build()));
2179 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2180
2181 // .. to the left window
2182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2183 injectMotionEvent(mDispatcher,
2184 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2185 AINPUT_SOURCE_MOUSE)
2186 .deviceId(mouseDeviceId)
2187 .downTime(baseTime + 10)
2188 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002189 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002190 .x(110)
2191 .y(100))
2192 .build()));
2193 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2194 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2195 // Now tap the left window
2196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2197 injectMotionEvent(mDispatcher,
2198 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2199 AINPUT_SOURCE_TOUCHSCREEN)
2200 .deviceId(touchDeviceId)
2201 .downTime(baseTime + 40)
2202 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002203 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002204 .x(100)
2205 .y(100))
2206 .build()));
2207 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2208 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2209
2210 // release tap
2211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2212 injectMotionEvent(mDispatcher,
2213 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2214 AINPUT_SOURCE_TOUCHSCREEN)
2215 .deviceId(touchDeviceId)
2216 .downTime(baseTime + 40)
2217 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002218 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002219 .x(100)
2220 .y(100))
2221 .build()));
2222 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2223
2224 // Tap the window on the right
2225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2226 injectMotionEvent(mDispatcher,
2227 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2228 AINPUT_SOURCE_TOUCHSCREEN)
2229 .deviceId(touchDeviceId)
2230 .downTime(baseTime + 60)
2231 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002232 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002233 .x(300)
2234 .y(100))
2235 .build()));
2236 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2237
2238 // release tap
2239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2240 injectMotionEvent(mDispatcher,
2241 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2242 AINPUT_SOURCE_TOUCHSCREEN)
2243 .deviceId(touchDeviceId)
2244 .downTime(baseTime + 60)
2245 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002246 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002247 .x(300)
2248 .y(100))
2249 .build()));
2250 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2251
2252 // No more events
2253 leftWindow->assertNoEvents();
2254 rightWindow->assertNoEvents();
2255}
2256
2257/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002258 * Start hovering in a window. While this hover is still active, make another window appear on top.
2259 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2260 * While the top window is present, the hovering is stopped.
2261 * Later, hovering gets resumed again.
2262 * Ensure that new hover gesture is handled correctly.
2263 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2264 * to the window that's currently being hovered over.
2265 */
2266TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2267 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2268 sp<FakeWindowHandle> window =
2269 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2270 window->setFrame(Rect(0, 0, 200, 200));
2271
2272 // Only a single window is present at first
2273 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2274
2275 // Start hovering in the window
2276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2277 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2278 .build());
2279 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2280
2281 // Now, an obscuring window appears!
2282 sp<FakeWindowHandle> obscuringWindow =
2283 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2284 ADISPLAY_ID_DEFAULT,
2285 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2286 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2287 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2288 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2289 obscuringWindow->setNoInputChannel(true);
2290 obscuringWindow->setFocusable(false);
2291 obscuringWindow->setAlpha(1.0);
2292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2293
2294 // While this new obscuring window is present, the hovering is stopped
2295 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2296 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2297 .build());
2298 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2299
2300 // Now the obscuring window goes away.
2301 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2302
2303 // And a new hover gesture starts.
2304 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2305 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2306 .build());
2307 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2308}
2309
2310/**
2311 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2312 * the obscuring window.
2313 */
2314TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2316 sp<FakeWindowHandle> window =
2317 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2318 window->setFrame(Rect(0, 0, 200, 200));
2319
2320 // Only a single window is present at first
2321 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2322
2323 // Start hovering in the window
2324 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2325 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2326 .build());
2327 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2328
2329 // Now, an obscuring window appears!
2330 sp<FakeWindowHandle> obscuringWindow =
2331 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2332 ADISPLAY_ID_DEFAULT,
2333 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2334 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2335 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2336 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2337 obscuringWindow->setNoInputChannel(true);
2338 obscuringWindow->setFocusable(false);
2339 obscuringWindow->setAlpha(1.0);
2340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2341
2342 // While this new obscuring window is present, the hovering continues. The event can't go to the
2343 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2344 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2345 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2346 .build());
2347 obscuringWindow->assertNoEvents();
2348 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2349
2350 // Now the obscuring window goes away.
2351 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2352
2353 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2354 // so it should generate a HOVER_ENTER
2355 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2356 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2357 .build());
2358 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2359
2360 // Now the MOVE should be getting dispatched normally
2361 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2362 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2363 .build());
2364 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2365}
2366
2367/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002368 * Two windows: a window on the left and a window on the right.
2369 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2370 * down. Then, on the left window, also place second touch pointer down.
2371 * This test tries to reproduce a crash.
2372 * In the buggy implementation, second pointer down on the left window would cause a crash.
2373 */
2374TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2376 sp<FakeWindowHandle> leftWindow =
2377 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2378 leftWindow->setFrame(Rect(0, 0, 200, 200));
2379
2380 sp<FakeWindowHandle> rightWindow =
2381 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2382 rightWindow->setFrame(Rect(200, 0, 400, 200));
2383
2384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2385
2386 const int32_t touchDeviceId = 4;
2387 const int32_t mouseDeviceId = 6;
2388 NotifyMotionArgs args;
2389
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;
2464 NotifyMotionArgs args;
2465
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002466 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2468 .deviceId(touchDeviceId)
2469 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2470 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002471 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002472 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2473 .deviceId(touchDeviceId)
2474 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2475 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2476 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002477 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002478 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2479 .deviceId(touchDeviceId)
2480 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2481 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2482 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002483 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2484 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2485 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2486
2487 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2489 .deviceId(mouseDeviceId)
2490 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2491 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2492 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002493
2494 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002495 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002496 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2497
Prabir Pradhan678438e2023-04-13 19:32:51 +00002498 mDispatcher->notifyMotion(
2499 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2500 .deviceId(mouseDeviceId)
2501 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2502 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2503 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2504 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002505 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2506
2507 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002508 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2509 .deviceId(touchDeviceId)
2510 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2511 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2512 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002513 // The pointer_down event should be ignored
2514 window->assertNoEvents();
2515}
2516
2517/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002518 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2519 * the injected event.
2520 */
2521TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2522 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2523 sp<FakeWindowHandle> window =
2524 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2525 window->setFrame(Rect(0, 0, 400, 400));
2526
2527 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2528
2529 const int32_t touchDeviceId = 4;
2530 NotifyMotionArgs args;
2531 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2532 // completion.
2533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2534 injectMotionEvent(mDispatcher,
2535 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2536 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002537 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002538 .x(50)
2539 .y(50))
2540 .build()));
2541 window->consumeMotionEvent(
2542 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2543
2544 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2545 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2547 .deviceId(touchDeviceId)
2548 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2549 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002550
2551 window->consumeMotionEvent(
2552 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2554}
2555
2556/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002557 * This test is similar to the test above, but the sequence of injected events is different.
2558 *
2559 * Two windows: a window on the left and a window on the right.
2560 * Mouse is hovered over the left window.
2561 * Next, we tap on the left window, where the cursor was last seen.
2562 *
2563 * After that, we inject one finger down onto the right window, and then a second finger down onto
2564 * the left window.
2565 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2566 * window (first), and then another on the left window (second).
2567 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2568 * In the buggy implementation, second finger down on the left window would cause a crash.
2569 */
2570TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2572 sp<FakeWindowHandle> leftWindow =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2574 leftWindow->setFrame(Rect(0, 0, 200, 200));
2575
2576 sp<FakeWindowHandle> rightWindow =
2577 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2578 rightWindow->setFrame(Rect(200, 0, 400, 200));
2579
2580 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2581
2582 const int32_t mouseDeviceId = 6;
2583 const int32_t touchDeviceId = 4;
2584 // Hover over the left window. Keep the cursor there.
2585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2586 injectMotionEvent(mDispatcher,
2587 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2588 AINPUT_SOURCE_MOUSE)
2589 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002590 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002591 .x(50)
2592 .y(50))
2593 .build()));
2594 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2595
2596 // Tap on left window
2597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2598 injectMotionEvent(mDispatcher,
2599 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2600 AINPUT_SOURCE_TOUCHSCREEN)
2601 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002602 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002603 .x(100)
2604 .y(100))
2605 .build()));
2606
2607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2608 injectMotionEvent(mDispatcher,
2609 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2610 AINPUT_SOURCE_TOUCHSCREEN)
2611 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002612 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002613 .x(100)
2614 .y(100))
2615 .build()));
2616 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2617 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2618 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2619
2620 // First finger down on right window
2621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2622 injectMotionEvent(mDispatcher,
2623 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2624 AINPUT_SOURCE_TOUCHSCREEN)
2625 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002626 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002627 .x(300)
2628 .y(100))
2629 .build()));
2630 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2631
2632 // Second finger down on the left window
2633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2634 injectMotionEvent(mDispatcher,
2635 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2636 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002637 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002638 .x(300)
2639 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002640 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002641 .x(100)
2642 .y(100))
2643 .build()));
2644 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2645 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2646
2647 // No more events
2648 leftWindow->assertNoEvents();
2649 rightWindow->assertNoEvents();
2650}
2651
2652/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002653 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2654 * While the touch is down, new hover events from the stylus device should be ignored. After the
2655 * touch is gone, stylus hovering should start working again.
2656 */
2657TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2658 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2659 sp<FakeWindowHandle> window =
2660 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2661 window->setFrame(Rect(0, 0, 200, 200));
2662
2663 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2664
2665 const int32_t stylusDeviceId = 5;
2666 const int32_t touchDeviceId = 4;
2667 // Start hovering with stylus
2668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2669 injectMotionEvent(mDispatcher,
2670 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2671 AINPUT_SOURCE_STYLUS)
2672 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002673 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002674 .x(50)
2675 .y(50))
2676 .build()));
2677 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2678
2679 // Finger down on the window
2680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2681 injectMotionEvent(mDispatcher,
2682 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2683 AINPUT_SOURCE_TOUCHSCREEN)
2684 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002685 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002686 .x(100)
2687 .y(100))
2688 .build()));
2689 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2690 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2691
2692 // Try to continue hovering with stylus. Since we are already down, injection should fail
2693 ASSERT_EQ(InputEventInjectionResult::FAILED,
2694 injectMotionEvent(mDispatcher,
2695 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2696 AINPUT_SOURCE_STYLUS)
2697 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002698 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002699 .x(50)
2700 .y(50))
2701 .build()));
2702 // No event should be sent. This event should be ignored because a pointer from another device
2703 // is already down.
2704
2705 // Lift up the finger
2706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2707 injectMotionEvent(mDispatcher,
2708 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2709 AINPUT_SOURCE_TOUCHSCREEN)
2710 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002711 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002712 .x(100)
2713 .y(100))
2714 .build()));
2715 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2716
2717 // Now that the touch is gone, stylus hovering should start working again
2718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2719 injectMotionEvent(mDispatcher,
2720 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2721 AINPUT_SOURCE_STYLUS)
2722 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002723 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002724 .x(50)
2725 .y(50))
2726 .build()));
2727 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2728 // No more events
2729 window->assertNoEvents();
2730}
2731
2732/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002733 * A spy window above a window with no input channel.
2734 * Start hovering with a stylus device, and then tap with it.
2735 * Ensure spy window receives the entire sequence.
2736 */
2737TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2739 sp<FakeWindowHandle> spyWindow =
2740 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2741 spyWindow->setFrame(Rect(0, 0, 200, 200));
2742 spyWindow->setTrustedOverlay(true);
2743 spyWindow->setSpy(true);
2744 sp<FakeWindowHandle> window =
2745 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2746 window->setNoInputChannel(true);
2747 window->setFrame(Rect(0, 0, 200, 200));
2748
2749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2750
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002751 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2753 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2754 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002755 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2756 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, 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_HOVER_EXIT));
2761
2762 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, 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_DOWN));
2767
2768 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, 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_UP));
2773
2774 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002775 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2776 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2777 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002778 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2779 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002783 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2784
2785 // No more events
2786 spyWindow->assertNoEvents();
2787 window->assertNoEvents();
2788}
2789
2790/**
2791 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2792 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2793 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2794 * While the mouse is down, new move events from the touch device should be ignored.
2795 */
2796TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2798 sp<FakeWindowHandle> spyWindow =
2799 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2800 spyWindow->setFrame(Rect(0, 0, 200, 200));
2801 spyWindow->setTrustedOverlay(true);
2802 spyWindow->setSpy(true);
2803 sp<FakeWindowHandle> window =
2804 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2805 window->setFrame(Rect(0, 0, 200, 200));
2806
2807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2808
2809 const int32_t mouseDeviceId = 7;
2810 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002811
2812 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002813 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2814 .deviceId(mouseDeviceId)
2815 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2816 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002817 spyWindow->consumeMotionEvent(
2818 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2819 window->consumeMotionEvent(
2820 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2821
2822 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2824 .deviceId(touchDeviceId)
2825 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2826 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002827 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2828 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2829 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2830 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2831
Prabir Pradhan678438e2023-04-13 19:32:51 +00002832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2833 .deviceId(touchDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2835 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002836 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2837 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2838
2839 // Pilfer the stream
2840 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2841 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2842
Prabir Pradhan678438e2023-04-13 19:32:51 +00002843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2844 .deviceId(touchDeviceId)
2845 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2846 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002847 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2848
2849 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2851 .deviceId(mouseDeviceId)
2852 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2853 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2854 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002855
2856 spyWindow->consumeMotionEvent(
2857 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2858 spyWindow->consumeMotionEvent(
2859 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2860 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2861
Prabir Pradhan678438e2023-04-13 19:32:51 +00002862 mDispatcher->notifyMotion(
2863 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2864 .deviceId(mouseDeviceId)
2865 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2866 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2867 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2868 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002869 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2870 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2871
2872 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2874 .deviceId(mouseDeviceId)
2875 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2876 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2877 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002878 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2879 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2880
2881 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2883 .deviceId(touchDeviceId)
2884 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2885 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002886
2887 // No more events
2888 spyWindow->assertNoEvents();
2889 window->assertNoEvents();
2890}
2891
2892/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002893 * On the display, have a single window, and also an area where there's no window.
2894 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2895 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2896 */
2897TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2899 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002900 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002901
2902 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002903
2904 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002905 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002906
2907 mDispatcher->waitForIdle();
2908 window->assertNoEvents();
2909
2910 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002911 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002912 mDispatcher->waitForIdle();
2913 window->consumeMotionDown();
2914}
2915
2916/**
2917 * Same test as above, but instead of touching the empty space, the first touch goes to
2918 * non-touchable window.
2919 */
2920TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2921 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2922 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002923 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002924 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2925 window1->setTouchable(false);
2926 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002927 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002928 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2929
2930 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2931
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002932 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002933 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002934
2935 mDispatcher->waitForIdle();
2936 window1->assertNoEvents();
2937 window2->assertNoEvents();
2938
2939 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002940 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002941 mDispatcher->waitForIdle();
2942 window2->consumeMotionDown();
2943}
2944
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002945/**
2946 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2947 * to the event time of the first ACTION_DOWN sent to the particular window.
2948 */
2949TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2951 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002952 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002953 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2954 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002955 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002956 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2957
2958 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2959
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002960 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002961 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002962
2963 mDispatcher->waitForIdle();
2964 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002965 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002966 window2->assertNoEvents();
2967 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2968 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2969 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2970
2971 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002972 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002973 mDispatcher->waitForIdle();
2974 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002975 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002976 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2977 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2978 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2979 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2980
2981 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002982 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002983 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002984 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002985
2986 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002987 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002988 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002989 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002990
2991 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2992 window1->consumeMotionMove();
2993 window1->assertNoEvents();
2994
2995 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002996 mDispatcher->notifyMotion(
2997 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002998 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002999 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003000
Prabir Pradhan678438e2023-04-13 19:32:51 +00003001 mDispatcher->notifyMotion(
3002 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003003 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003004 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003005}
3006
Garfield Tandf26e862020-07-01 20:18:19 -07003007TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003009 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003010 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003011 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003012 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003013 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003014 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003015
3016 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3017
3018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3019
3020 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003022 injectMotionEvent(mDispatcher,
3023 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3024 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003026 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003027 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003028
3029 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003031 injectMotionEvent(mDispatcher,
3032 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3033 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003034 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003035 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003036 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3037 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003038
3039 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003041 injectMotionEvent(mDispatcher,
3042 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3043 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003045 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003046 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3047 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003048
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003050 injectMotionEvent(mDispatcher,
3051 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3052 AINPUT_SOURCE_MOUSE)
3053 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3054 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003055 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003056 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003057 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003058
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003060 injectMotionEvent(mDispatcher,
3061 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3062 AINPUT_SOURCE_MOUSE)
3063 .buttonState(0)
3064 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003065 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003066 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003067 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003068
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003070 injectMotionEvent(mDispatcher,
3071 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3072 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003073 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003074 .build()));
3075 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3076
3077 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003079 injectMotionEvent(mDispatcher,
3080 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3081 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003082 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003083 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003084 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003085
3086 // No more events
3087 windowLeft->assertNoEvents();
3088 windowRight->assertNoEvents();
3089}
3090
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091/**
3092 * Put two fingers down (and don't release them) and click the mouse button.
3093 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3094 * currently active gesture should be canceled, and the new one should proceed.
3095 */
3096TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3098 sp<FakeWindowHandle> window =
3099 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3100 window->setFrame(Rect(0, 0, 600, 800));
3101
3102 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3103
3104 const int32_t touchDeviceId = 4;
3105 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106
3107 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003108 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3109 .deviceId(touchDeviceId)
3110 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112
Prabir Pradhan678438e2023-04-13 19:32:51 +00003113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3114 .deviceId(touchDeviceId)
3115 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3116 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3117 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3119 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3120
3121 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3123 .deviceId(mouseDeviceId)
3124 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3125 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3126 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3128 WithPointerCount(2u)));
3129 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3130
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(
3132 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3133 .deviceId(mouseDeviceId)
3134 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3135 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3136 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3137 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003138 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3139
3140 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3141 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003142 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3143 .deviceId(touchDeviceId)
3144 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3145 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3146 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003147 window->assertNoEvents();
3148}
3149
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003150TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3152
3153 sp<FakeWindowHandle> spyWindow =
3154 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3155 spyWindow->setFrame(Rect(0, 0, 600, 800));
3156 spyWindow->setTrustedOverlay(true);
3157 spyWindow->setSpy(true);
3158 sp<FakeWindowHandle> window =
3159 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3160 window->setFrame(Rect(0, 0, 600, 800));
3161
3162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3163 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3164
3165 // Send mouse cursor to the window
3166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3167 injectMotionEvent(mDispatcher,
3168 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3169 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003170 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003171 .x(100)
3172 .y(100))
3173 .build()));
3174
3175 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3176 WithSource(AINPUT_SOURCE_MOUSE)));
3177 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3178 WithSource(AINPUT_SOURCE_MOUSE)));
3179
3180 window->assertNoEvents();
3181 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003182}
3183
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003184TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3186
3187 sp<FakeWindowHandle> spyWindow =
3188 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3189 spyWindow->setFrame(Rect(0, 0, 600, 800));
3190 spyWindow->setTrustedOverlay(true);
3191 spyWindow->setSpy(true);
3192 sp<FakeWindowHandle> window =
3193 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3194 window->setFrame(Rect(0, 0, 600, 800));
3195
3196 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3197 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3198
3199 // Send mouse cursor to the window
3200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3201 injectMotionEvent(mDispatcher,
3202 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3203 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003204 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003205 .x(100)
3206 .y(100))
3207 .build()));
3208
3209 // Move mouse cursor
3210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3211 injectMotionEvent(mDispatcher,
3212 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3213 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003214 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003215 .x(110)
3216 .y(110))
3217 .build()));
3218
3219 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3220 WithSource(AINPUT_SOURCE_MOUSE)));
3221 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3222 WithSource(AINPUT_SOURCE_MOUSE)));
3223 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3224 WithSource(AINPUT_SOURCE_MOUSE)));
3225 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3226 WithSource(AINPUT_SOURCE_MOUSE)));
3227 // Touch down on the window
3228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3229 injectMotionEvent(mDispatcher,
3230 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3231 AINPUT_SOURCE_TOUCHSCREEN)
3232 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003233 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003234 .x(200)
3235 .y(200))
3236 .build()));
3237 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3238 WithSource(AINPUT_SOURCE_MOUSE)));
3239 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3240 WithSource(AINPUT_SOURCE_MOUSE)));
3241 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3242 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3243 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3244 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3245
3246 // pilfer the motion, retaining the gesture on the spy window.
3247 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3248 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3249 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3250
3251 // Touch UP on the window
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3253 injectMotionEvent(mDispatcher,
3254 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3255 AINPUT_SOURCE_TOUCHSCREEN)
3256 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003257 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003258 .x(200)
3259 .y(200))
3260 .build()));
3261 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3262 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3263
3264 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3265 // to send a new gesture. It should again go to both windows (spy and the window below), just
3266 // like the first gesture did, before pilfering. The window configuration has not changed.
3267
3268 // One more tap - DOWN
3269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3270 injectMotionEvent(mDispatcher,
3271 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3272 AINPUT_SOURCE_TOUCHSCREEN)
3273 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003274 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003275 .x(250)
3276 .y(250))
3277 .build()));
3278 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3279 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3280 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3281 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3282
3283 // Touch UP on the window
3284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3285 injectMotionEvent(mDispatcher,
3286 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3287 AINPUT_SOURCE_TOUCHSCREEN)
3288 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003289 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003290 .x(250)
3291 .y(250))
3292 .build()));
3293 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3294 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3295 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3296 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3297
3298 window->assertNoEvents();
3299 spyWindow->assertNoEvents();
3300}
3301
Garfield Tandf26e862020-07-01 20:18:19 -07003302// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3303// directly in this test.
3304TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003305 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003306 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003307 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003308 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003309
3310 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3311
3312 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3313
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003315 injectMotionEvent(mDispatcher,
3316 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3317 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003318 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003319 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003320 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003321 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003323 injectMotionEvent(mDispatcher,
3324 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3325 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003327 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003328 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3329 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003330
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003332 injectMotionEvent(mDispatcher,
3333 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3334 AINPUT_SOURCE_MOUSE)
3335 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3336 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003337 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003338 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003339 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003340
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003342 injectMotionEvent(mDispatcher,
3343 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3344 AINPUT_SOURCE_MOUSE)
3345 .buttonState(0)
3346 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003347 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003348 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003349 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003350
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003351 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003352 injectMotionEvent(mDispatcher,
3353 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3354 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003355 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003356 .build()));
3357 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3358
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003359 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3360 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3361 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003362 injectMotionEvent(mDispatcher,
3363 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3364 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003365 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003366 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003367 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003368}
3369
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003370/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003371 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3372 * is generated.
3373 */
3374TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3376 sp<FakeWindowHandle> window =
3377 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3378 window->setFrame(Rect(0, 0, 1200, 800));
3379
3380 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3381
3382 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3383
3384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3385 injectMotionEvent(mDispatcher,
3386 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3387 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003388 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003389 .x(300)
3390 .y(400))
3391 .build()));
3392 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3393
3394 // Remove the window, but keep the channel.
3395 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3396 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3397}
3398
3399/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003400 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3401 */
3402TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3404 sp<FakeWindowHandle> window =
3405 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3406 window->setFrame(Rect(0, 0, 100, 100));
3407
3408 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3409
3410 const int32_t mouseDeviceId = 7;
3411 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003412
3413 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3415 .deviceId(mouseDeviceId)
3416 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3417 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003418 window->consumeMotionEvent(
3419 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3420
3421 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3423 .deviceId(touchDeviceId)
3424 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3425 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003426
3427 window->consumeMotionEvent(
3428 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3429 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3430}
3431
3432/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003433 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003434 * The tap causes a HOVER_EXIT event to be generated because the current event
3435 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003436 */
3437TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3439 sp<FakeWindowHandle> window =
3440 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3441 window->setFrame(Rect(0, 0, 100, 100));
3442
3443 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3444
3445 // Inject a hover_move from mouse.
3446 NotifyMotionArgs motionArgs =
3447 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3448 ADISPLAY_ID_DEFAULT, {{50, 50}});
3449 motionArgs.xCursorPosition = 50;
3450 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003451 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003452 ASSERT_NO_FATAL_FAILURE(
3453 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3454 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003455
3456 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003457 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3458 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3459 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003460 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003461 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3462 WithSource(AINPUT_SOURCE_MOUSE))));
3463
3464 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003465 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3466 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3467
Prabir Pradhan678438e2023-04-13 19:32:51 +00003468 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3469 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003470 ASSERT_NO_FATAL_FAILURE(
3471 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3472 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3473}
3474
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003475TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3477 sp<FakeWindowHandle> windowDefaultDisplay =
3478 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3479 ADISPLAY_ID_DEFAULT);
3480 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3481 sp<FakeWindowHandle> windowSecondDisplay =
3482 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3483 SECOND_DISPLAY_ID);
3484 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3485
3486 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3487 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3488
3489 // Set cursor position in window in default display and check that hover enter and move
3490 // events are generated.
3491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3492 injectMotionEvent(mDispatcher,
3493 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3494 AINPUT_SOURCE_MOUSE)
3495 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003496 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003497 .x(300)
3498 .y(600))
3499 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003500 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003501
3502 // Remove all windows in secondary display and check that no event happens on window in
3503 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003504 mDispatcher->setInputWindows(
3505 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003506 windowDefaultDisplay->assertNoEvents();
3507
3508 // Move cursor position in window in default display and check that only hover move
3509 // event is generated and not hover enter event.
3510 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3511 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3513 injectMotionEvent(mDispatcher,
3514 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3515 AINPUT_SOURCE_MOUSE)
3516 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003517 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003518 .x(400)
3519 .y(700))
3520 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003521 windowDefaultDisplay->consumeMotionEvent(
3522 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3523 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003524 windowDefaultDisplay->assertNoEvents();
3525}
3526
Garfield Tan00f511d2019-06-12 16:55:40 -07003527TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003528 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003529
3530 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003531 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003532 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003533 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003534 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003535 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003536
3537 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3538
Arthur Hung72d8dc32020-03-28 00:48:39 +00003539 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003540
3541 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3542 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003544 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003545 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003546 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003547 windowRight->assertNoEvents();
3548}
3549
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003550TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003552 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3553 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003554 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003555
Arthur Hung72d8dc32020-03-28 00:48:39 +00003556 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003557 setFocusedWindow(window);
3558
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003559 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003560
Prabir Pradhan678438e2023-04-13 19:32:51 +00003561 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003562
3563 // Window should receive key down event.
3564 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3565
3566 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3567 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003568 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003569 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003570 AKEY_EVENT_FLAG_CANCELED);
3571}
3572
3573TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003575 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3576 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003577
Arthur Hung72d8dc32020-03-28 00:48:39 +00003578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003579
Prabir Pradhan678438e2023-04-13 19:32:51 +00003580 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3581 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003582
3583 // Window should receive motion down event.
3584 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3585
3586 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3587 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003588 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003589 window->consumeMotionEvent(
3590 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003591}
3592
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003593TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3595 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3596 "Fake Window", ADISPLAY_ID_DEFAULT);
3597
3598 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3599
3600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3601 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3602 .build());
3603
3604 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3605
3606 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3607 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3608 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3609
3610 // After the device has been reset, a new hovering stream can be sent to the window
3611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3612 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3613 .build());
3614 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3615}
3616
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003617TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003619 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3620 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003621 window->setFocusable(true);
3622
3623 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3624 setFocusedWindow(window);
3625
3626 window->consumeFocusEvent(true);
3627
Prabir Pradhan678438e2023-04-13 19:32:51 +00003628 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003629 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3630 const nsecs_t injectTime = keyArgs.eventTime;
3631 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003632 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003633 // The dispatching time should be always greater than or equal to intercept key timeout.
3634 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3635 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3636 std::chrono::nanoseconds(interceptKeyTimeout).count());
3637}
3638
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003639/**
3640 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3641 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003642TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003644 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3645 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003646 window->setFocusable(true);
3647
3648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3649 setFocusedWindow(window);
3650
3651 window->consumeFocusEvent(true);
3652
Prabir Pradhan678438e2023-04-13 19:32:51 +00003653 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003654 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003655
3656 // Set a value that's significantly larger than the default consumption timeout. If the
3657 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3658 mFakePolicy->setInterceptKeyTimeout(600ms);
3659 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3660 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003661 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3662}
3663
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003664/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003665 * Two windows. First is a regular window. Second does not overlap with the first, and has
3666 * WATCH_OUTSIDE_TOUCH.
3667 * Both windows are owned by the same UID.
3668 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3669 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3670 */
3671TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3673 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3674 "First Window", ADISPLAY_ID_DEFAULT);
3675 window->setFrame(Rect{0, 0, 100, 100});
3676
3677 sp<FakeWindowHandle> outsideWindow =
3678 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3679 ADISPLAY_ID_DEFAULT);
3680 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3681 outsideWindow->setWatchOutsideTouch(true);
3682 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3684
3685 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003686 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3687 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3688 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003689 window->consumeMotionDown();
3690 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3691 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3692 outsideWindow->consumeMotionEvent(
3693 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3694}
3695
3696/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003697 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3698 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3699 * ACTION_OUTSIDE event is sent per gesture.
3700 */
3701TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3702 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3705 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003706 window->setWatchOutsideTouch(true);
3707 window->setFrame(Rect{0, 0, 100, 100});
3708 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003709 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3710 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003711 secondWindow->setFrame(Rect{100, 100, 200, 200});
3712 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003713 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3714 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003715 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3717
3718 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003719 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3720 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3721 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003722 window->assertNoEvents();
3723 secondWindow->assertNoEvents();
3724
3725 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3726 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003727 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3728 ADISPLAY_ID_DEFAULT,
3729 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003730 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3731 window->consumeMotionEvent(
3732 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003733 secondWindow->consumeMotionDown();
3734 thirdWindow->assertNoEvents();
3735
3736 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3737 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(
3739 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3740 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003741 window->assertNoEvents();
3742 secondWindow->consumeMotionMove();
3743 thirdWindow->consumeMotionDown();
3744}
3745
Prabir Pradhan814fe082022-07-22 20:22:18 +00003746TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3749 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003750 window->setFocusable(true);
3751
Patrick Williamsd828f302023-04-28 17:52:08 -05003752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003753 setFocusedWindow(window);
3754
3755 window->consumeFocusEvent(true);
3756
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3758 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3759 mDispatcher->notifyKey(keyDown);
3760 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003761
3762 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3763 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3764
3765 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003766 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003767
3768 window->consumeFocusEvent(false);
3769
Prabir Pradhan678438e2023-04-13 19:32:51 +00003770 mDispatcher->notifyKey(keyDown);
3771 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003772 window->assertNoEvents();
3773}
3774
Arthur Hung96483742022-11-15 03:30:48 +00003775TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3777 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3778 "Fake Window", ADISPLAY_ID_DEFAULT);
3779 // Ensure window is non-split and have some transform.
3780 window->setPreventSplitting(true);
3781 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003782 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003783
3784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3785 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3786 {50, 50}))
3787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3788 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3789
3790 const MotionEvent secondFingerDownEvent =
3791 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3792 .displayId(ADISPLAY_ID_DEFAULT)
3793 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003794 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3795 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003796 .build();
3797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3798 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3799 InputEventInjectionSync::WAIT_FOR_RESULT))
3800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3801
3802 const MotionEvent* event = window->consumeMotion();
3803 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3804 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3805 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3806 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3807 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3808}
3809
Harry Cuttsb166c002023-05-09 13:06:05 +00003810TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3812 sp<FakeWindowHandle> window =
3813 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3814 window->setFrame(Rect(0, 0, 400, 400));
3815 sp<FakeWindowHandle> trustedOverlay =
3816 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3817 ADISPLAY_ID_DEFAULT);
3818 trustedOverlay->setSpy(true);
3819 trustedOverlay->setTrustedOverlay(true);
3820
3821 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3822
3823 // Start a three-finger touchpad swipe
3824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3825 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3826 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3827 .build());
3828 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3829 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3830 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3831 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3832 .build());
3833 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3834 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3835 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3836 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3837 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3838 .build());
3839
3840 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3841 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3842 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3843
3844 // Move the swipe a bit
3845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3846 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3847 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3848 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3849 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3850 .build());
3851
3852 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3853
3854 // End the swipe
3855 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3856 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3857 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3858 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3859 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3860 .build());
3861 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3862 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3863 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3864 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3865 .build());
3866 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3867 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3868 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3869 .build());
3870
3871 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3872 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3873 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3874
3875 window->assertNoEvents();
3876}
3877
3878TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3880 sp<FakeWindowHandle> window =
3881 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3882 window->setFrame(Rect(0, 0, 400, 400));
3883 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3884
3885 // Start a three-finger touchpad swipe
3886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3887 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3888 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3889 .build());
3890 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3891 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3892 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3893 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3894 .build());
3895 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3896 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3897 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3898 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3899 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3900 .build());
3901
3902 // Move the swipe a bit
3903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3904 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3905 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3906 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3907 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3908 .build());
3909
3910 // End the swipe
3911 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3912 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3913 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3914 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3915 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3916 .build());
3917 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3918 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3919 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3920 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3921 .build());
3922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3923 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3924 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3925 .build());
3926
3927 window->assertNoEvents();
3928}
3929
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003930/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003931 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3932 * the first pointer.
3933 * Ensure that the second pointer is not sent to the window.
3934 *
3935 * The subsequent gesture should be correctly delivered to the window.
3936 */
3937TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3939 sp<FakeWindowHandle> window =
3940 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3941 window->setFrame(Rect(0, 0, 400, 400));
3942 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3943
3944 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3945 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3946 .downTime(baseTime + 10)
3947 .eventTime(baseTime + 10)
3948 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3949 .build());
3950
3951 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3952
3953 // We need a new window object for the same window, because dispatcher will store objects by
3954 // reference. That means that the testing code and the dispatcher will refer to the same shared
3955 // object. Calling window->setTransform here would affect dispatcher's comparison
3956 // of the old window to the new window, since both the old window and the new window would be
3957 // updated to the same value.
3958 sp<FakeWindowHandle> windowDup = window->duplicate();
3959
3960 // Change the transform so that the orientation is now different from original.
3961 windowDup->setWindowTransform(0, -1, 1, 0);
3962
3963 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3964
3965 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3966
3967 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3968 .downTime(baseTime + 10)
3969 .eventTime(baseTime + 30)
3970 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3971 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3972 .build());
3973
3974 // Finish the gesture and start a new one. Ensure the new gesture is sent to the window
3975 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3976 .downTime(baseTime + 10)
3977 .eventTime(baseTime + 40)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3979 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3980 .build());
3981 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3982 .downTime(baseTime + 10)
3983 .eventTime(baseTime + 50)
3984 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3985 .build());
3986
3987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3988 .downTime(baseTime + 60)
3989 .eventTime(baseTime + 60)
3990 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
3991 .build());
3992
3993 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3994}
3995
3996/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003997 * Ensure the correct coordinate spaces are used by InputDispatcher.
3998 *
3999 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4000 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4001 * space.
4002 */
4003class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4004public:
4005 void SetUp() override {
4006 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004007 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004008 }
4009
4010 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4011 gui::DisplayInfo info;
4012 info.displayId = displayId;
4013 info.transform = transform;
4014 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004015 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004016 }
4017
4018 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4019 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004020 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004021 }
4022
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004023 void removeAllWindowsAndDisplays() {
4024 mDisplayInfos.clear();
4025 mWindowInfos.clear();
4026 }
4027
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004028 // Set up a test scenario where the display has a scaled projection and there are two windows
4029 // on the display.
4030 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4031 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4032 // respectively.
4033 ui::Transform displayTransform;
4034 displayTransform.set(2, 0, 0, 4);
4035 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4036
4037 std::shared_ptr<FakeApplicationHandle> application =
4038 std::make_shared<FakeApplicationHandle>();
4039
4040 // Add two windows to the display. Their frames are represented in the display space.
4041 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004042 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4043 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004044 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4045 addWindow(firstWindow);
4046
4047 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004048 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4049 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004050 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4051 addWindow(secondWindow);
4052 return {std::move(firstWindow), std::move(secondWindow)};
4053 }
4054
4055private:
4056 std::vector<gui::DisplayInfo> mDisplayInfos;
4057 std::vector<gui::WindowInfo> mWindowInfos;
4058};
4059
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004060TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004061 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4062 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004063 // selected so that if the hit test was performed with the point and the bounds being in
4064 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004065 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4066 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4067 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004068
4069 firstWindow->consumeMotionDown();
4070 secondWindow->assertNoEvents();
4071}
4072
4073// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4074// the event should be treated as being in the logical display space.
4075TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4076 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4077 // Send down to the first window. The point is represented in the logical display space. The
4078 // point is selected so that if the hit test was done in logical display space, then it would
4079 // end up in the incorrect window.
4080 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4081 PointF{75 * 2, 55 * 4});
4082
4083 firstWindow->consumeMotionDown();
4084 secondWindow->assertNoEvents();
4085}
4086
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004087// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4088// event should be treated as being in the logical display space.
4089TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4090 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4091
4092 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4093 ui::Transform injectedEventTransform;
4094 injectedEventTransform.set(matrix);
4095 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4096 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4097
4098 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4099 .displayId(ADISPLAY_ID_DEFAULT)
4100 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004101 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004102 .x(untransformedPoint.x)
4103 .y(untransformedPoint.y))
4104 .build();
4105 event.transform(matrix);
4106
4107 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4108 InputEventInjectionSync::WAIT_FOR_RESULT);
4109
4110 firstWindow->consumeMotionDown();
4111 secondWindow->assertNoEvents();
4112}
4113
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004114TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4115 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4116
4117 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004118 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4119 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4120 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004121
4122 firstWindow->assertNoEvents();
4123 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004124 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004125 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4126
4127 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4128 EXPECT_EQ(300, event->getRawX(0));
4129 EXPECT_EQ(880, event->getRawY(0));
4130
4131 // Ensure that the x and y values are in the window's coordinate space.
4132 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4133 // the logical display space. This will be the origin of the window space.
4134 EXPECT_EQ(100, event->getX(0));
4135 EXPECT_EQ(80, event->getY(0));
4136}
4137
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004138/** Ensure consistent behavior of InputDispatcher in all orientations. */
4139class InputDispatcherDisplayOrientationFixture
4140 : public InputDispatcherDisplayProjectionTest,
4141 public ::testing::WithParamInterface<ui::Rotation> {};
4142
4143// This test verifies the touchable region of a window for all rotations of the display by tapping
4144// in different locations on the display, specifically points close to the four corners of a
4145// window.
4146TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4147 constexpr static int32_t displayWidth = 400;
4148 constexpr static int32_t displayHeight = 800;
4149
4150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4151
4152 const auto rotation = GetParam();
4153
4154 // Set up the display with the specified rotation.
4155 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4156 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4157 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4158 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4159 logicalDisplayWidth, logicalDisplayHeight);
4160 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4161
4162 // Create a window with its bounds determined in the logical display.
4163 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4164 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4165 sp<FakeWindowHandle> window =
4166 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4167 window->setFrame(frameInDisplay, displayTransform);
4168 addWindow(window);
4169
4170 // The following points in logical display space should be inside the window.
4171 static const std::array<vec2, 4> insidePoints{
4172 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4173 for (const auto pointInsideWindow : insidePoints) {
4174 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4175 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004176 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4177 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4178 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004179 window->consumeMotionDown();
4180
Prabir Pradhan678438e2023-04-13 19:32:51 +00004181 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4182 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4183 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004184 window->consumeMotionUp();
4185 }
4186
4187 // The following points in logical display space should be outside the window.
4188 static const std::array<vec2, 5> outsidePoints{
4189 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4190 for (const auto pointOutsideWindow : outsidePoints) {
4191 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4192 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004193 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4194 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4195 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004196
Prabir Pradhan678438e2023-04-13 19:32:51 +00004197 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4198 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4199 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004200 }
4201 window->assertNoEvents();
4202}
4203
4204// Run the precision tests for all rotations.
4205INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4206 InputDispatcherDisplayOrientationFixture,
4207 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4208 ui::ROTATION_270),
4209 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4210 return ftl::enum_string(testParamInfo.param);
4211 });
4212
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004213using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4214 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004215
4216class TransferTouchFixture : public InputDispatcherTest,
4217 public ::testing::WithParamInterface<TransferFunction> {};
4218
4219TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004221
4222 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004223 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004224 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4225 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004226 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004227 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004228 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4229 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004230 sp<FakeWindowHandle> wallpaper =
4231 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4232 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004233 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004234 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004235
4236 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004237 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4238 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004239
Svet Ganov5d3bc372020-01-26 23:11:07 -08004240 // Only the first window should get the down event
4241 firstWindow->consumeMotionDown();
4242 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004243 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004245 // Transfer touch to the second window
4246 TransferFunction f = GetParam();
4247 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4248 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004249 // The first window gets cancel and the second gets down
4250 firstWindow->consumeMotionCancel();
4251 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004252 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004253
4254 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004255 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4256 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004257 // The first window gets no events and the second gets up
4258 firstWindow->assertNoEvents();
4259 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004260 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004261}
4262
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004263/**
4264 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4265 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4266 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4267 * natural to the user.
4268 * In this test, we are sending a pointer to both spy window and first window. We then try to
4269 * transfer touch to the second window. The dispatcher should identify the first window as the
4270 * one that should lose the gesture, and therefore the action should be to move the gesture from
4271 * the first window to the second.
4272 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4273 * the other API, as well.
4274 */
4275TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4277
4278 // Create a couple of windows + a spy window
4279 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004280 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004281 spyWindow->setTrustedOverlay(true);
4282 spyWindow->setSpy(true);
4283 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004284 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004285 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004286 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004287
4288 // Add the windows to the dispatcher
4289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4290
4291 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004292 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4293 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004294 // Only the first window and spy should get the down event
4295 spyWindow->consumeMotionDown();
4296 firstWindow->consumeMotionDown();
4297
4298 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4299 // if f === 'transferTouch'.
4300 TransferFunction f = GetParam();
4301 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4302 ASSERT_TRUE(success);
4303 // The first window gets cancel and the second gets down
4304 firstWindow->consumeMotionCancel();
4305 secondWindow->consumeMotionDown();
4306
4307 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004308 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4309 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004310 // The first window gets no events and the second+spy get up
4311 firstWindow->assertNoEvents();
4312 spyWindow->consumeMotionUp();
4313 secondWindow->consumeMotionUp();
4314}
4315
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004316TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004318
4319 PointF touchPoint = {10, 10};
4320
4321 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004322 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004323 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4324 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004325 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004326 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004327 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4328 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004329 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004330
4331 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004332 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004333
4334 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004335 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4336 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4337 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004338 // Only the first window should get the down event
4339 firstWindow->consumeMotionDown();
4340 secondWindow->assertNoEvents();
4341
4342 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004343 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4344 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004345 // Only the first window should get the pointer down event
4346 firstWindow->consumeMotionPointerDown(1);
4347 secondWindow->assertNoEvents();
4348
4349 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004350 TransferFunction f = GetParam();
4351 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4352 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004353 // The first window gets cancel and the second gets down and pointer down
4354 firstWindow->consumeMotionCancel();
4355 secondWindow->consumeMotionDown();
4356 secondWindow->consumeMotionPointerDown(1);
4357
4358 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004359 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4360 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004361 // The first window gets nothing and the second gets pointer up
4362 firstWindow->assertNoEvents();
4363 secondWindow->consumeMotionPointerUp(1);
4364
4365 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004366 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4367 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004368 // The first window gets nothing and the second gets up
4369 firstWindow->assertNoEvents();
4370 secondWindow->consumeMotionUp();
4371}
4372
Arthur Hungc539dbb2022-12-08 07:45:36 +00004373TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4375
4376 // Create a couple of windows
4377 sp<FakeWindowHandle> firstWindow =
4378 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4379 ADISPLAY_ID_DEFAULT);
4380 firstWindow->setDupTouchToWallpaper(true);
4381 sp<FakeWindowHandle> secondWindow =
4382 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4383 ADISPLAY_ID_DEFAULT);
4384 secondWindow->setDupTouchToWallpaper(true);
4385
4386 sp<FakeWindowHandle> wallpaper1 =
4387 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4388 wallpaper1->setIsWallpaper(true);
4389
4390 sp<FakeWindowHandle> wallpaper2 =
4391 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4392 wallpaper2->setIsWallpaper(true);
4393 // Add the windows to the dispatcher
4394 mDispatcher->setInputWindows(
4395 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4396
4397 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004398 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4399 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004400
4401 // Only the first window should get the down event
4402 firstWindow->consumeMotionDown();
4403 secondWindow->assertNoEvents();
4404 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4405 wallpaper2->assertNoEvents();
4406
4407 // Transfer touch focus to the second window
4408 TransferFunction f = GetParam();
4409 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4410 ASSERT_TRUE(success);
4411
4412 // The first window gets cancel and the second gets down
4413 firstWindow->consumeMotionCancel();
4414 secondWindow->consumeMotionDown();
4415 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4416 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4417
4418 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004419 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4420 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004421 // The first window gets no events and the second gets up
4422 firstWindow->assertNoEvents();
4423 secondWindow->consumeMotionUp();
4424 wallpaper1->assertNoEvents();
4425 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4426}
4427
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004428// For the cases of single pointer touch and two pointers non-split touch, the api's
4429// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4430// for the case where there are multiple pointers split across several windows.
4431INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4432 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004433 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4434 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004435 return dispatcher->transferTouch(destChannelToken,
4436 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004437 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004438 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4439 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004440 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004441 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004442 }));
4443
Svet Ganov5d3bc372020-01-26 23:11:07 -08004444TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004446
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004447 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004448 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4449 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004450 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004451
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004452 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004453 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4454 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004455 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004456
4457 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004459
4460 PointF pointInFirst = {300, 200};
4461 PointF pointInSecond = {300, 600};
4462
4463 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4465 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4466 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004467 // Only the first window should get the down event
4468 firstWindow->consumeMotionDown();
4469 secondWindow->assertNoEvents();
4470
4471 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004472 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4473 ADISPLAY_ID_DEFAULT,
4474 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004475 // The first window gets a move and the second a down
4476 firstWindow->consumeMotionMove();
4477 secondWindow->consumeMotionDown();
4478
4479 // Transfer touch focus to the second window
4480 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4481 // The first window gets cancel and the new gets pointer down (it already saw down)
4482 firstWindow->consumeMotionCancel();
4483 secondWindow->consumeMotionPointerDown(1);
4484
4485 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004486 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4487 ADISPLAY_ID_DEFAULT,
4488 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004489 // The first window gets nothing and the second gets pointer up
4490 firstWindow->assertNoEvents();
4491 secondWindow->consumeMotionPointerUp(1);
4492
4493 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004494 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4495 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004496 // The first window gets nothing and the second gets up
4497 firstWindow->assertNoEvents();
4498 secondWindow->consumeMotionUp();
4499}
4500
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004501// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4502// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4503// touch is not supported, so the touch should continue on those windows and the transferred-to
4504// window should get nothing.
4505TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4507
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004508 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004509 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4510 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004511 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004512
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004513 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004514 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4515 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004516 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004517
4518 // Add the windows to the dispatcher
4519 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4520
4521 PointF pointInFirst = {300, 200};
4522 PointF pointInSecond = {300, 600};
4523
4524 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004525 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4526 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4527 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004528 // Only the first window should get the down event
4529 firstWindow->consumeMotionDown();
4530 secondWindow->assertNoEvents();
4531
4532 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004533 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4534 ADISPLAY_ID_DEFAULT,
4535 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004536 // The first window gets a move and the second a down
4537 firstWindow->consumeMotionMove();
4538 secondWindow->consumeMotionDown();
4539
4540 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004541 const bool transferred =
4542 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004543 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4544 ASSERT_FALSE(transferred);
4545 firstWindow->assertNoEvents();
4546 secondWindow->assertNoEvents();
4547
4548 // The rest of the dispatch should proceed as normal
4549 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004550 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4551 ADISPLAY_ID_DEFAULT,
4552 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004553 // The first window gets MOVE and the second gets pointer up
4554 firstWindow->consumeMotionMove();
4555 secondWindow->consumeMotionUp();
4556
4557 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004558 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4559 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004560 // The first window gets nothing and the second gets up
4561 firstWindow->consumeMotionUp();
4562 secondWindow->assertNoEvents();
4563}
4564
Arthur Hungabbb9d82021-09-01 14:52:30 +00004565// This case will create two windows and one mirrored window on the default display and mirror
4566// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4567// the windows info of second display before default display.
4568TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4570 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004571 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004572 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004573 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004574 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004575 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004576
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004577 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004578 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004579
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004580 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004581 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004583 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004584 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004585
4586 // Update window info, let it find window handle of second display first.
4587 mDispatcher->setInputWindows(
4588 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4589 {ADISPLAY_ID_DEFAULT,
4590 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4591
4592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4593 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4594 {50, 50}))
4595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4596
4597 // Window should receive motion event.
4598 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4599
4600 // Transfer touch focus
4601 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4602 secondWindowInPrimary->getToken()));
4603 // The first window gets cancel.
4604 firstWindowInPrimary->consumeMotionCancel();
4605 secondWindowInPrimary->consumeMotionDown();
4606
4607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4608 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4609 ADISPLAY_ID_DEFAULT, {150, 50}))
4610 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4611 firstWindowInPrimary->assertNoEvents();
4612 secondWindowInPrimary->consumeMotionMove();
4613
4614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4615 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4616 {150, 50}))
4617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4618 firstWindowInPrimary->assertNoEvents();
4619 secondWindowInPrimary->consumeMotionUp();
4620}
4621
4622// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4623// 'transferTouch' api.
4624TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4626 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004627 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004628 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004629 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004630 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004631 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004632
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004633 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004634 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004635
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004636 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004637 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004638
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004639 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004640 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004641
4642 // Update window info, let it find window handle of second display first.
4643 mDispatcher->setInputWindows(
4644 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4645 {ADISPLAY_ID_DEFAULT,
4646 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4647
4648 // Touch on second display.
4649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4650 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4652
4653 // Window should receive motion event.
4654 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4655
4656 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004657 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004658
4659 // The first window gets cancel.
4660 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4661 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4662
4663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4664 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4665 SECOND_DISPLAY_ID, {150, 50}))
4666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4667 firstWindowInPrimary->assertNoEvents();
4668 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4669
4670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4671 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4673 firstWindowInPrimary->assertNoEvents();
4674 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4675}
4676
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004677TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004678 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004679 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4680 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004681
Vishnu Nair47074b82020-08-14 11:54:47 -07004682 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004684 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004685
4686 window->consumeFocusEvent(true);
4687
Prabir Pradhan678438e2023-04-13 19:32:51 +00004688 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004689
4690 // Window should receive key down event.
4691 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004692
4693 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004694 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004695 mFakePolicy->assertUserActivityPoked();
4696}
4697
4698TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4700 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4701 "Fake Window", ADISPLAY_ID_DEFAULT);
4702
4703 window->setDisableUserActivity(true);
4704 window->setFocusable(true);
4705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4706 setFocusedWindow(window);
4707
4708 window->consumeFocusEvent(true);
4709
4710 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4711
4712 // Window should receive key down event.
4713 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4714
4715 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004716 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004717 mFakePolicy->assertUserActivityNotPoked();
4718}
4719
4720TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4723 "Fake Window", ADISPLAY_ID_DEFAULT);
4724
4725 window->setFocusable(true);
4726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4727 setFocusedWindow(window);
4728
4729 window->consumeFocusEvent(true);
4730
4731 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4732 mDispatcher->waitForIdle();
4733
4734 // System key is not passed down
4735 window->assertNoEvents();
4736
4737 // Should have poked user activity
4738 mFakePolicy->assertUserActivityPoked();
4739}
4740
4741TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4743 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4744 "Fake Window", ADISPLAY_ID_DEFAULT);
4745
4746 window->setFocusable(true);
4747 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4748 setFocusedWindow(window);
4749
4750 window->consumeFocusEvent(true);
4751
4752 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4753 mDispatcher->waitForIdle();
4754
4755 // System key is not passed down
4756 window->assertNoEvents();
4757
4758 // Should have poked user activity
4759 mFakePolicy->assertUserActivityPoked();
4760}
4761
4762TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4763 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4764 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4765 "Fake Window", ADISPLAY_ID_DEFAULT);
4766
4767 window->setDisableUserActivity(true);
4768 window->setFocusable(true);
4769 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4770 setFocusedWindow(window);
4771
4772 window->consumeFocusEvent(true);
4773
4774 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4775 mDispatcher->waitForIdle();
4776
4777 // System key is not passed down
4778 window->assertNoEvents();
4779
4780 // Should have poked user activity
4781 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004782}
4783
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004784TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4787 "Fake Window", ADISPLAY_ID_DEFAULT);
4788
4789 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4790
4791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4792 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4793 ADISPLAY_ID_DEFAULT, {100, 100}))
4794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4795
4796 window->consumeMotionEvent(
4797 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4798
4799 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004800 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004801 mFakePolicy->assertUserActivityPoked();
4802}
4803
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004804TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004806 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4807 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004808
Arthur Hung72d8dc32020-03-28 00:48:39 +00004809 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004810
Prabir Pradhan678438e2023-04-13 19:32:51 +00004811 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004812 mDispatcher->waitForIdle();
4813
4814 window->assertNoEvents();
4815}
4816
4817// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4818TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004820 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4821 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004822
Arthur Hung72d8dc32020-03-28 00:48:39 +00004823 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004824
4825 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004826 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004827 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004828 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4829 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004830
4831 // Window should receive only the motion event
4832 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4833 window->assertNoEvents(); // Key event or focus event will not be received
4834}
4835
arthurhungea3f4fc2020-12-21 23:18:53 +08004836TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4837 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4838
arthurhungea3f4fc2020-12-21 23:18:53 +08004839 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004840 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4841 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004842 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004843
arthurhungea3f4fc2020-12-21 23:18:53 +08004844 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004845 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4846 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004847 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004848
4849 // Add the windows to the dispatcher
4850 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4851
4852 PointF pointInFirst = {300, 200};
4853 PointF pointInSecond = {300, 600};
4854
4855 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004856 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4857 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4858 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004859 // Only the first window should get the down event
4860 firstWindow->consumeMotionDown();
4861 secondWindow->assertNoEvents();
4862
4863 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004864 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4865 ADISPLAY_ID_DEFAULT,
4866 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004867 // The first window gets a move and the second a down
4868 firstWindow->consumeMotionMove();
4869 secondWindow->consumeMotionDown();
4870
4871 // Send pointer cancel to the second window
4872 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004873 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004874 {pointInFirst, pointInSecond});
4875 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004876 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004877 // The first window gets move and the second gets cancel.
4878 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4879 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4880
4881 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004882 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4883 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004884 // The first window gets up and the second gets nothing.
4885 firstWindow->consumeMotionUp();
4886 secondWindow->assertNoEvents();
4887}
4888
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004889TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4891
4892 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004893 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004894 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4895 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4896 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4897 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4898
Harry Cutts33476232023-01-30 19:57:29 +00004899 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004900 window->assertNoEvents();
4901 mDispatcher->waitForIdle();
4902}
4903
chaviwd1c23182019-12-20 18:44:56 -08004904class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004905public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004906 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004907 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004908 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004909 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004910 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004911 }
4912
chaviwd1c23182019-12-20 18:44:56 -08004913 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4914
4915 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004916 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4917 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004918 }
4919
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004920 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4921
4922 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4923
chaviwd1c23182019-12-20 18:44:56 -08004924 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004925 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004926 expectedDisplayId, expectedFlags);
4927 }
4928
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004929 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004930 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004931 expectedDisplayId, expectedFlags);
4932 }
4933
chaviwd1c23182019-12-20 18:44:56 -08004934 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004935 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004936 expectedDisplayId, expectedFlags);
4937 }
4938
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004939 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004940 mInputReceiver->consumeMotionEvent(
4941 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4942 WithDisplayId(expectedDisplayId),
4943 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004944 }
4945
Arthur Hungfbfa5722021-11-16 02:45:54 +00004946 void consumeMotionPointerDown(int32_t pointerIdx) {
4947 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4948 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004949 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004950 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004951 }
4952
Evan Rosky84f07f02021-04-16 10:42:42 -07004953 MotionEvent* consumeMotion() {
4954 InputEvent* event = mInputReceiver->consume();
4955 if (!event) {
4956 ADD_FAILURE() << "No event was produced";
4957 return nullptr;
4958 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004959 if (event->getType() != InputEventType::MOTION) {
4960 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004961 return nullptr;
4962 }
4963 return static_cast<MotionEvent*>(event);
4964 }
4965
chaviwd1c23182019-12-20 18:44:56 -08004966 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4967
4968private:
4969 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004970};
4971
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004972using InputDispatcherMonitorTest = InputDispatcherTest;
4973
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004974/**
4975 * Two entities that receive touch: A window, and a global monitor.
4976 * The touch goes to the window, and then the window disappears.
4977 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4978 * for the monitor, as well.
4979 * 1. foregroundWindow
4980 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4981 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004982TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4984 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004985 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004986
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004987 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004988
4989 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4991 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4992 {100, 200}))
4993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4994
4995 // Both the foreground window and the global monitor should receive the touch down
4996 window->consumeMotionDown();
4997 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4998
4999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5000 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5001 ADISPLAY_ID_DEFAULT, {110, 200}))
5002 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5003
5004 window->consumeMotionMove();
5005 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5006
5007 // Now the foreground window goes away
5008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5009 window->consumeMotionCancel();
5010 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5011
5012 // If more events come in, there will be no more foreground window to send them to. This will
5013 // cause a cancel for the monitor, as well.
5014 ASSERT_EQ(InputEventInjectionResult::FAILED,
5015 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5016 ADISPLAY_ID_DEFAULT, {120, 200}))
5017 << "Injection should fail because the window was removed";
5018 window->assertNoEvents();
5019 // Global monitor now gets the cancel
5020 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5021}
5022
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005023TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005025 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5026 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005028
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005029 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005030
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005032 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005034 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005035 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005036}
5037
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005038TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5039 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005040
Chris Yea209fde2020-07-22 13:54:51 -07005041 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005042 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5043 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005044 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005045
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005047 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005048 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005049 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005050 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005051
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005052 // Pilfer pointers from the monitor.
5053 // This should not do anything and the window should continue to receive events.
5054 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005055
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005057 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5058 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005060
5061 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5062 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005063}
5064
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005065TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005067 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5068 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005069 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5070 window->setWindowOffset(20, 40);
5071 window->setWindowTransform(0, 1, -1, 0);
5072
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005073 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005074
5075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5076 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5078 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5079 MotionEvent* event = monitor.consumeMotion();
5080 // Even though window has transform, gesture monitor must not.
5081 ASSERT_EQ(ui::Transform(), event->getTransform());
5082}
5083
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005084TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005086 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005087
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005088 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005089 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005090 << "Injection should fail if there is a monitor, but no touchable window";
5091 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005092}
5093
chaviw81e2bb92019-12-18 15:03:51 -08005094TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005096 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5097 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005098
Arthur Hung72d8dc32020-03-28 00:48:39 +00005099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005100
5101 NotifyMotionArgs motionArgs =
5102 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5103 ADISPLAY_ID_DEFAULT);
5104
Prabir Pradhan678438e2023-04-13 19:32:51 +00005105 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005106 // Window should receive motion down event.
5107 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5108
5109 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005110 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005111 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5112 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5113 motionArgs.pointerCoords[0].getX() - 10);
5114
Prabir Pradhan678438e2023-04-13 19:32:51 +00005115 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005116 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005117 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005118}
5119
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005120/**
5121 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5122 * the device default right away. In the test scenario, we check both the default value,
5123 * and the action of enabling / disabling.
5124 */
5125TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005127 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5128 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005129 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005130
5131 // Set focused application.
5132 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005133 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005134
5135 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005137 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005138 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005139
5140 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005141 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005142 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005143 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005144
5145 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005146 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005147 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005148 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005149 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005151 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005152 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005153
5154 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005155 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005157 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005158
5159 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005160 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005161 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005162 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005163 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005164 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005165 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005166 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005167
5168 window->assertNoEvents();
5169}
5170
Gang Wange9087892020-01-07 12:17:14 -05005171TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005173 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5174 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005175
5176 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005177 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005178
Arthur Hung72d8dc32020-03-28 00:48:39 +00005179 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005180 setFocusedWindow(window);
5181
Harry Cutts33476232023-01-30 19:57:29 +00005182 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005183
Prabir Pradhan678438e2023-04-13 19:32:51 +00005184 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5185 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005186
5187 InputEvent* event = window->consume();
5188 ASSERT_NE(event, nullptr);
5189
5190 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5191 ASSERT_NE(verified, nullptr);
5192 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5193
5194 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5195 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5196 ASSERT_EQ(keyArgs.source, verified->source);
5197 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5198
5199 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5200
5201 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005202 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005203 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005204 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5205 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5206 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5207 ASSERT_EQ(0, verifiedKey.repeatCount);
5208}
5209
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005210TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005212 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5213 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005214
5215 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5216
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005217 ui::Transform transform;
5218 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5219
5220 gui::DisplayInfo displayInfo;
5221 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5222 displayInfo.transform = transform;
5223
Patrick Williamsd828f302023-04-28 17:52:08 -05005224 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005225
Prabir Pradhan678438e2023-04-13 19:32:51 +00005226 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005227 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5228 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005229 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005230
5231 InputEvent* event = window->consume();
5232 ASSERT_NE(event, nullptr);
5233
5234 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5235 ASSERT_NE(verified, nullptr);
5236 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5237
5238 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5239 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5240 EXPECT_EQ(motionArgs.source, verified->source);
5241 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5242
5243 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5244
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005245 const vec2 rawXY =
5246 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5247 motionArgs.pointerCoords[0].getXYValue());
5248 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5249 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005250 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005251 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005252 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005253 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5254 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5255}
5256
chaviw09c8d2d2020-08-24 15:48:26 -07005257/**
5258 * Ensure that separate calls to sign the same data are generating the same key.
5259 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5260 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5261 * tests.
5262 */
5263TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5264 KeyEvent event = getTestKeyEvent();
5265 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5266
5267 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5268 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5269 ASSERT_EQ(hmac1, hmac2);
5270}
5271
5272/**
5273 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5274 */
5275TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5276 KeyEvent event = getTestKeyEvent();
5277 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5278 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5279
5280 verifiedEvent.deviceId += 1;
5281 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5282
5283 verifiedEvent.source += 1;
5284 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5285
5286 verifiedEvent.eventTimeNanos += 1;
5287 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5288
5289 verifiedEvent.displayId += 1;
5290 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5291
5292 verifiedEvent.action += 1;
5293 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5294
5295 verifiedEvent.downTimeNanos += 1;
5296 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5297
5298 verifiedEvent.flags += 1;
5299 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5300
5301 verifiedEvent.keyCode += 1;
5302 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5303
5304 verifiedEvent.scanCode += 1;
5305 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5306
5307 verifiedEvent.metaState += 1;
5308 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5309
5310 verifiedEvent.repeatCount += 1;
5311 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5312}
5313
Vishnu Nair958da932020-08-21 17:12:37 -07005314TEST_F(InputDispatcherTest, SetFocusedWindow) {
5315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5316 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005317 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005318 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005319 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005320 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5321
5322 // Top window is also focusable but is not granted focus.
5323 windowTop->setFocusable(true);
5324 windowSecond->setFocusable(true);
5325 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5326 setFocusedWindow(windowSecond);
5327
5328 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5330 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005331
5332 // Focused window should receive event.
5333 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5334 windowTop->assertNoEvents();
5335}
5336
5337TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5339 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005340 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005341 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5342
5343 window->setFocusable(true);
5344 // Release channel for window is no longer valid.
5345 window->releaseChannel();
5346 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5347 setFocusedWindow(window);
5348
5349 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005350 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5351 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005352
5353 // window channel is invalid, so it should not receive any input event.
5354 window->assertNoEvents();
5355}
5356
5357TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5359 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005360 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005361 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005362 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5363
Vishnu Nair958da932020-08-21 17:12:37 -07005364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5365 setFocusedWindow(window);
5366
5367 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005368 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5369 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005370
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005371 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005372 window->assertNoEvents();
5373}
5374
5375TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5377 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005378 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005379 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005380 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005381 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5382
5383 windowTop->setFocusable(true);
5384 windowSecond->setFocusable(true);
5385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5386 setFocusedWindow(windowTop);
5387 windowTop->consumeFocusEvent(true);
5388
Chavi Weingarten847e8512023-03-29 00:26:09 +00005389 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5390 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005391 windowSecond->consumeFocusEvent(true);
5392 windowTop->consumeFocusEvent(false);
5393
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5395 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005396
5397 // Focused window should receive event.
5398 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5399}
5400
Chavi Weingarten847e8512023-03-29 00:26:09 +00005401TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005402 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5403 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005404 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005405 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005406 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005407 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5408
5409 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005410 windowSecond->setFocusable(false);
5411 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005412 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005413 setFocusedWindow(windowTop);
5414 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005415
Chavi Weingarten847e8512023-03-29 00:26:09 +00005416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5417 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005418
5419 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005420 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005421 windowSecond->assertNoEvents();
5422}
5423
5424TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5425 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5426 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005427 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005428 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005429 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5430 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005431 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5432
5433 window->setFocusable(true);
5434 previousFocusedWindow->setFocusable(true);
5435 window->setVisible(false);
5436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5437 setFocusedWindow(previousFocusedWindow);
5438 previousFocusedWindow->consumeFocusEvent(true);
5439
5440 // Requesting focus on invisible window takes focus from currently focused window.
5441 setFocusedWindow(window);
5442 previousFocusedWindow->consumeFocusEvent(false);
5443
5444 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005446 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5447 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005448
5449 // Window does not get focus event or key down.
5450 window->assertNoEvents();
5451
5452 // Window becomes visible.
5453 window->setVisible(true);
5454 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5455
5456 // Window receives focus event.
5457 window->consumeFocusEvent(true);
5458 // Focused window receives key down.
5459 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5460}
5461
Vishnu Nair599f1412021-06-21 10:39:58 -07005462TEST_F(InputDispatcherTest, DisplayRemoved) {
5463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5464 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005465 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005466 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5467
5468 // window is granted focus.
5469 window->setFocusable(true);
5470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5471 setFocusedWindow(window);
5472 window->consumeFocusEvent(true);
5473
5474 // When a display is removed window loses focus.
5475 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5476 window->consumeFocusEvent(false);
5477}
5478
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005479/**
5480 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5481 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5482 * of the 'slipperyEnterWindow'.
5483 *
5484 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5485 * a way so that the touched location is no longer covered by the top window.
5486 *
5487 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5488 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5489 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5490 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5491 * with ACTION_DOWN).
5492 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5493 * window moved itself away from the touched location and had Flag::SLIPPERY.
5494 *
5495 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5496 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5497 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5498 *
5499 * In this test, we ensure that the event received by the bottom window has
5500 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5501 */
5502TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005503 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005504 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005505
5506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5507 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5508
5509 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005510 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005511 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005512 // Make sure this one overlaps the bottom window
5513 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5514 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5515 // one. Windows with the same owner are not considered to be occluding each other.
5516 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5517
5518 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005519 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005520 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5521
5522 mDispatcher->setInputWindows(
5523 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5524
5525 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5528 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005529 slipperyExitWindow->consumeMotionDown();
5530 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5531 mDispatcher->setInputWindows(
5532 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5533
Prabir Pradhan678438e2023-04-13 19:32:51 +00005534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5536 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005537
5538 slipperyExitWindow->consumeMotionCancel();
5539
5540 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5541 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5542}
5543
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005544/**
5545 * Two windows, one on the left and another on the right. The left window is slippery. The right
5546 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5547 * touch moves from the left window into the right window, the gesture should continue to go to the
5548 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5549 * reproduces a crash.
5550 */
5551TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5553
5554 sp<FakeWindowHandle> leftSlipperyWindow =
5555 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5556 leftSlipperyWindow->setSlippery(true);
5557 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5558
5559 sp<FakeWindowHandle> rightDropTouchesWindow =
5560 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5561 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5562 rightDropTouchesWindow->setDropInput(true);
5563
5564 mDispatcher->setInputWindows(
5565 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5566
5567 // Start touch in the left window
5568 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5569 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5570 .build());
5571 leftSlipperyWindow->consumeMotionDown();
5572
5573 // And move it into the right window
5574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5575 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5576 .build());
5577
5578 // Since the right window isn't eligible to receive input, touch does not slip.
5579 // The left window continues to receive the gesture.
5580 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5581 rightDropTouchesWindow->assertNoEvents();
5582}
5583
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005584TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005585 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5587
5588 sp<FakeWindowHandle> leftWindow =
5589 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5590 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005591 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005592
5593 sp<FakeWindowHandle> rightSpy =
5594 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5595 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005596 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005597 rightSpy->setSpy(true);
5598 rightSpy->setTrustedOverlay(true);
5599
5600 sp<FakeWindowHandle> rightWindow =
5601 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5602 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005603 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005604
5605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5606
5607 // Touch in the left window
5608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5609 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5610 .build());
5611 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5612 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005613 ASSERT_NO_FATAL_FAILURE(
5614 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005615
5616 // Touch another finger over the right windows
5617 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5618 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5619 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5620 .build());
5621 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5622 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5623 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5624 mDispatcher->waitForIdle();
5625 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005626 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5627 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005628
5629 // Release finger over left window. The UP actions are not treated as device interaction.
5630 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5631 // is part of the UP action, we do not treat this as device interaction.
5632 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5633 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5634 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5635 .build());
5636 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5637 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5638 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5639 mDispatcher->waitForIdle();
5640 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5641
5642 // Move remaining finger
5643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5644 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5645 .build());
5646 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5647 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5648 mDispatcher->waitForIdle();
5649 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005650 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005651
5652 // Release all fingers
5653 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5654 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5655 .build());
5656 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5657 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5658 mDispatcher->waitForIdle();
5659 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5660}
5661
5662TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5664
5665 sp<FakeWindowHandle> window =
5666 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5667 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005668 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005669
5670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5671 setFocusedWindow(window);
5672 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5673
5674 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5675 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5676 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005677 ASSERT_NO_FATAL_FAILURE(
5678 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005679
5680 // The UP actions are not treated as device interaction.
5681 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5682 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5683 mDispatcher->waitForIdle();
5684 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5685}
5686
Garfield Tan1c7bc862020-01-28 13:24:04 -08005687class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5688protected:
5689 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5690 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5691
Chris Yea209fde2020-07-22 13:54:51 -07005692 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005693 sp<FakeWindowHandle> mWindow;
5694
5695 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005696 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005697 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005698 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005699 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005700 ASSERT_EQ(OK, mDispatcher->start());
5701
5702 setUpWindow();
5703 }
5704
5705 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005706 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005707 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005708
Vishnu Nair47074b82020-08-14 11:54:47 -07005709 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005711 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005712 mWindow->consumeFocusEvent(true);
5713 }
5714
Chris Ye2ad95392020-09-01 13:44:44 -07005715 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005716 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005717 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005718 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005719 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005720
5721 // Window should receive key down event.
5722 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5723 }
5724
5725 void expectKeyRepeatOnce(int32_t repeatCount) {
5726 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5727 InputEvent* repeatEvent = mWindow->consume();
5728 ASSERT_NE(nullptr, repeatEvent);
5729
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005730 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005731
5732 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5733 uint32_t eventAction = repeatKeyEvent->getAction();
5734 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5735 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5736 }
5737
Chris Ye2ad95392020-09-01 13:44:44 -07005738 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005739 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005740 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005741 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005742 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005743
5744 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005745 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005746 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005747 }
5748};
5749
5750TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005751 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005752 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5753 expectKeyRepeatOnce(repeatCount);
5754 }
5755}
5756
5757TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005758 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005759 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5760 expectKeyRepeatOnce(repeatCount);
5761 }
Harry Cutts33476232023-01-30 19:57:29 +00005762 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005763 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005764 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5765 expectKeyRepeatOnce(repeatCount);
5766 }
5767}
5768
5769TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005770 sendAndConsumeKeyDown(/*deviceId=*/1);
5771 expectKeyRepeatOnce(/*repeatCount=*/1);
5772 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005773 mWindow->assertNoEvents();
5774}
5775
5776TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005777 sendAndConsumeKeyDown(/*deviceId=*/1);
5778 expectKeyRepeatOnce(/*repeatCount=*/1);
5779 sendAndConsumeKeyDown(/*deviceId=*/2);
5780 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005781 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005782 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005783 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005784 expectKeyRepeatOnce(/*repeatCount=*/2);
5785 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005786 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005787 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005788 mWindow->assertNoEvents();
5789}
5790
5791TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005792 sendAndConsumeKeyDown(/*deviceId=*/1);
5793 expectKeyRepeatOnce(/*repeatCount=*/1);
5794 sendAndConsumeKeyDown(/*deviceId=*/2);
5795 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005796 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005797 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005798 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005799 mWindow->assertNoEvents();
5800}
5801
liushenxiang42232912021-05-21 20:24:09 +08005802TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5803 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005804 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005805 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005806 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5807 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5808 mWindow->assertNoEvents();
5809}
5810
Garfield Tan1c7bc862020-01-28 13:24:04 -08005811TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005812 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005813 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005814 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5815 InputEvent* repeatEvent = mWindow->consume();
5816 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5817 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5818 IdGenerator::getSource(repeatEvent->getId()));
5819 }
5820}
5821
5822TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005823 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005824 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005825
5826 std::unordered_set<int32_t> idSet;
5827 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5828 InputEvent* repeatEvent = mWindow->consume();
5829 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5830 int32_t id = repeatEvent->getId();
5831 EXPECT_EQ(idSet.end(), idSet.find(id));
5832 idSet.insert(id);
5833 }
5834}
5835
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005836/* Test InputDispatcher for MultiDisplay */
5837class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5838public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005839 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005840 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005841
Chris Yea209fde2020-07-22 13:54:51 -07005842 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005843 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005844 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005845
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005846 // Set focus window for primary display, but focused display would be second one.
5847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005848 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005849 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005850 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005851 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005852
Chris Yea209fde2020-07-22 13:54:51 -07005853 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005854 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005855 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005856 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005857 // Set focus display to second one.
5858 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5859 // Set focus window for second display.
5860 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005861 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005862 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005863 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005864 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005865 }
5866
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005867 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005868 InputDispatcherTest::TearDown();
5869
Chris Yea209fde2020-07-22 13:54:51 -07005870 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005871 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005872 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005873 windowInSecondary.clear();
5874 }
5875
5876protected:
Chris Yea209fde2020-07-22 13:54:51 -07005877 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005878 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005879 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005880 sp<FakeWindowHandle> windowInSecondary;
5881};
5882
5883TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5884 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5886 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005888 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005889 windowInSecondary->assertNoEvents();
5890
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005891 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5893 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5894 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005895 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005896 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005897}
5898
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005899TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005900 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5902 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005903 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005904 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005905 windowInSecondary->assertNoEvents();
5906
5907 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005909 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005910 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005911 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005912
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005913 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005914 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005915
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005916 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005917 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005918 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005919
5920 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005921 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005922 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005923 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005924 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005925 windowInSecondary->assertNoEvents();
5926}
5927
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005928// Test per-display input monitors for motion event.
5929TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005930 FakeMonitorReceiver monitorInPrimary =
5931 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5932 FakeMonitorReceiver monitorInSecondary =
5933 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005934
5935 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5937 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005939 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005940 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005941 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005942 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005943
5944 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5946 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5947 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005948 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005949 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005950 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005951 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005952
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005953 // Lift up the touch from the second display
5954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5955 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5957 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5958 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5959
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005960 // Test inject a non-pointer motion event.
5961 // If specific a display, it will dispatch to the focused window of particular display,
5962 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5964 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005966 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005967 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005968 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005969 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005970}
5971
5972// Test per-display input monitors for key event.
5973TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005974 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005975 FakeMonitorReceiver monitorInPrimary =
5976 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5977 FakeMonitorReceiver monitorInSecondary =
5978 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005979
5980 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5982 << "Inject key 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->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005986 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005987}
5988
Vishnu Nair958da932020-08-21 17:12:37 -07005989TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5990 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005991 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005992 secondWindowInPrimary->setFocusable(true);
5993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5994 setFocusedWindow(secondWindowInPrimary);
5995 windowInPrimary->consumeFocusEvent(false);
5996 secondWindowInPrimary->consumeFocusEvent(true);
5997
5998 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6000 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006001 windowInPrimary->assertNoEvents();
6002 windowInSecondary->assertNoEvents();
6003 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6004}
6005
Arthur Hungdfd528e2021-12-08 13:23:04 +00006006TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6007 FakeMonitorReceiver monitorInPrimary =
6008 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6009 FakeMonitorReceiver monitorInSecondary =
6010 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6011
6012 // Test touch down on primary display.
6013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6014 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6015 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6016 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6017 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6018
6019 // Test touch down on second display.
6020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6021 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6023 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6024 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6025
6026 // Trigger cancel touch.
6027 mDispatcher->cancelCurrentTouch();
6028 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6029 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6030 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6031 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6032
6033 // Test inject a move motion event, no window/monitor should receive the event.
6034 ASSERT_EQ(InputEventInjectionResult::FAILED,
6035 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6036 ADISPLAY_ID_DEFAULT, {110, 200}))
6037 << "Inject motion event should return InputEventInjectionResult::FAILED";
6038 windowInPrimary->assertNoEvents();
6039 monitorInPrimary.assertNoEvents();
6040
6041 ASSERT_EQ(InputEventInjectionResult::FAILED,
6042 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6043 SECOND_DISPLAY_ID, {110, 200}))
6044 << "Inject motion event should return InputEventInjectionResult::FAILED";
6045 windowInSecondary->assertNoEvents();
6046 monitorInSecondary.assertNoEvents();
6047}
6048
Jackal Guof9696682018-10-05 12:23:23 +08006049class InputFilterTest : public InputDispatcherTest {
6050protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006051 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6052 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006053 NotifyMotionArgs motionArgs;
6054
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006055 motionArgs =
6056 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006057 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006058 motionArgs =
6059 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006060 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006061 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006062 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006063 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
6064 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006065 } else {
6066 mFakePolicy->assertFilterInputEventWasNotCalled();
6067 }
6068 }
6069
6070 void testNotifyKey(bool expectToBeFiltered) {
6071 NotifyKeyArgs keyArgs;
6072
6073 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006074 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006075 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006076 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006077 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006078
6079 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006080 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006081 } else {
6082 mFakePolicy->assertFilterInputEventWasNotCalled();
6083 }
6084 }
6085};
6086
6087// Test InputFilter for MotionEvent
6088TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6089 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6090 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6091 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6092
6093 // Enable InputFilter
6094 mDispatcher->setInputFilterEnabled(true);
6095 // Test touch on both primary and second display, and check if both events are filtered.
6096 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6097 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6098
6099 // Disable InputFilter
6100 mDispatcher->setInputFilterEnabled(false);
6101 // Test touch on both primary and second display, and check if both events aren't filtered.
6102 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6103 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6104}
6105
6106// Test InputFilter for KeyEvent
6107TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6108 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6109 testNotifyKey(/*expectToBeFiltered*/ false);
6110
6111 // Enable InputFilter
6112 mDispatcher->setInputFilterEnabled(true);
6113 // Send a key event, and check if it is filtered.
6114 testNotifyKey(/*expectToBeFiltered*/ true);
6115
6116 // Disable InputFilter
6117 mDispatcher->setInputFilterEnabled(false);
6118 // Send a key event, and check if it isn't filtered.
6119 testNotifyKey(/*expectToBeFiltered*/ false);
6120}
6121
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006122// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6123// logical display coordinate space.
6124TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6125 ui::Transform firstDisplayTransform;
6126 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6127 ui::Transform secondDisplayTransform;
6128 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6129
6130 std::vector<gui::DisplayInfo> displayInfos(2);
6131 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6132 displayInfos[0].transform = firstDisplayTransform;
6133 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6134 displayInfos[1].transform = secondDisplayTransform;
6135
Patrick Williamsd828f302023-04-28 17:52:08 -05006136 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006137
6138 // Enable InputFilter
6139 mDispatcher->setInputFilterEnabled(true);
6140
6141 // Ensure the correct transforms are used for the displays.
6142 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6143 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6144}
6145
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006146class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6147protected:
6148 virtual void SetUp() override {
6149 InputDispatcherTest::SetUp();
6150
6151 /**
6152 * We don't need to enable input filter to test the injected event policy, but we enabled it
6153 * here to make the tests more realistic, since this policy only matters when inputfilter is
6154 * on.
6155 */
6156 mDispatcher->setInputFilterEnabled(true);
6157
6158 std::shared_ptr<InputApplicationHandle> application =
6159 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006160 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6161 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006162
6163 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6164 mWindow->setFocusable(true);
6165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6166 setFocusedWindow(mWindow);
6167 mWindow->consumeFocusEvent(true);
6168 }
6169
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006170 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6171 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006172 KeyEvent event;
6173
6174 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6175 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6176 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006177 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006178 const int32_t additionalPolicyFlags =
6179 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006181 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006182 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6183 policyFlags | additionalPolicyFlags));
6184
6185 InputEvent* received = mWindow->consume();
6186 ASSERT_NE(nullptr, received);
6187 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006188 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006189 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6190 ASSERT_EQ(flags, keyEvent.getFlags());
6191 }
6192
6193 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6194 int32_t flags) {
6195 MotionEvent event;
6196 PointerProperties pointerProperties[1];
6197 PointerCoords pointerCoords[1];
6198 pointerProperties[0].clear();
6199 pointerProperties[0].id = 0;
6200 pointerCoords[0].clear();
6201 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6202 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6203
6204 ui::Transform identityTransform;
6205 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6206 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6207 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6208 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6209 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006210 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006211 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006212 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6213
6214 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006216 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006217 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6218 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::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006224 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6225 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006226 }
6227
6228private:
6229 sp<FakeWindowHandle> mWindow;
6230};
6231
6232TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006233 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6234 // filter. Without it, the event will no different from a regularly injected event, and the
6235 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006236 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6237 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006238}
6239
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006240TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006241 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006242 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006243 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6244}
6245
6246TEST_F(InputFilterInjectionPolicyTest,
6247 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6248 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006249 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006250 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006251}
6252
6253TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006254 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6255 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006256}
6257
chaviwfd6d3512019-03-25 13:23:49 -07006258class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006259 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006260 InputDispatcherTest::SetUp();
6261
Chris Yea209fde2020-07-22 13:54:51 -07006262 std::shared_ptr<FakeApplicationHandle> application =
6263 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006264 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006265 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006266 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006267
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006268 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006269 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006270 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006271
6272 // Set focused application.
6273 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006274 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006275
6276 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006277 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006278 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006279 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006280 }
6281
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006282 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006283 InputDispatcherTest::TearDown();
6284
6285 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006286 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006287 }
6288
6289protected:
6290 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006291 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006292 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006293};
6294
6295// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6296// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6297// the onPointerDownOutsideFocus callback.
6298TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006300 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6301 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006303 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006304
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006305 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006306 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6307}
6308
6309// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6310// DOWN on the window that doesn't have focus. Ensure no window received the
6311// onPointerDownOutsideFocus callback.
6312TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006314 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006316 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006317
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006318 ASSERT_TRUE(mDispatcher->waitForIdle());
6319 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006320}
6321
6322// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6323// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6324TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6326 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006327 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006328 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006329
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006330 ASSERT_TRUE(mDispatcher->waitForIdle());
6331 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006332}
6333
6334// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6335// DOWN on the window that already has focus. Ensure no window received the
6336// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006337TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006339 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006340 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006341 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006342 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006343
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006344 ASSERT_TRUE(mDispatcher->waitForIdle());
6345 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006346}
6347
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006348// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6349// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6350TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6351 const MotionEvent event =
6352 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6353 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006354 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006355 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6356 .build();
6357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6358 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6359 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6360
6361 ASSERT_TRUE(mDispatcher->waitForIdle());
6362 mFakePolicy->assertOnPointerDownWasNotCalled();
6363 // Ensure that the unfocused window did not receive any FOCUS events.
6364 mUnfocusedWindow->assertNoEvents();
6365}
6366
chaviwaf87b3e2019-10-01 16:59:28 -07006367// These tests ensures we can send touch events to a single client when there are multiple input
6368// windows that point to the same client token.
6369class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6370 virtual void SetUp() override {
6371 InputDispatcherTest::SetUp();
6372
Chris Yea209fde2020-07-22 13:54:51 -07006373 std::shared_ptr<FakeApplicationHandle> application =
6374 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006375 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6376 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006377 mWindow1->setFrame(Rect(0, 0, 100, 100));
6378
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006379 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6380 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006381 mWindow2->setFrame(Rect(100, 100, 200, 200));
6382
Arthur Hung72d8dc32020-03-28 00:48:39 +00006383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006384 }
6385
6386protected:
6387 sp<FakeWindowHandle> mWindow1;
6388 sp<FakeWindowHandle> mWindow2;
6389
6390 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006391 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006392 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6393 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006394 }
6395
6396 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6397 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006398 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006399 InputEvent* event = window->consume();
6400
6401 ASSERT_NE(nullptr, event) << name.c_str()
6402 << ": consumer should have returned non-NULL event.";
6403
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006404 ASSERT_EQ(InputEventType::MOTION, event->getType())
6405 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006406
6407 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006408 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006409 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006410
6411 for (size_t i = 0; i < points.size(); i++) {
6412 float expectedX = points[i].x;
6413 float expectedY = points[i].y;
6414
6415 EXPECT_EQ(expectedX, motionEvent.getX(i))
6416 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6417 << ", got " << motionEvent.getX(i);
6418 EXPECT_EQ(expectedY, motionEvent.getY(i))
6419 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6420 << ", got " << motionEvent.getY(i);
6421 }
6422 }
chaviw9eaa22c2020-07-01 16:21:27 -07006423
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006424 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006425 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006426 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6427 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006428
6429 // Always consume from window1 since it's the window that has the InputReceiver
6430 consumeMotionEvent(mWindow1, action, expectedPoints);
6431 }
chaviwaf87b3e2019-10-01 16:59:28 -07006432};
6433
6434TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6435 // Touch Window 1
6436 PointF touchedPoint = {10, 10};
6437 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006438 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006439
6440 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006441 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006442
6443 // Touch Window 2
6444 touchedPoint = {150, 150};
6445 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006446 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006447}
6448
chaviw9eaa22c2020-07-01 16:21:27 -07006449TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6450 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006451 mWindow2->setWindowScale(0.5f, 0.5f);
6452
6453 // Touch Window 1
6454 PointF touchedPoint = {10, 10};
6455 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006456 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006457 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006458 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006459
6460 // Touch Window 2
6461 touchedPoint = {150, 150};
6462 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006463 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6464 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006465
chaviw9eaa22c2020-07-01 16:21:27 -07006466 // Update the transform so rotation is set
6467 mWindow2->setWindowTransform(0, -1, 1, 0);
6468 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6469 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006470}
6471
chaviw9eaa22c2020-07-01 16:21:27 -07006472TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006473 mWindow2->setWindowScale(0.5f, 0.5f);
6474
6475 // Touch Window 1
6476 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6477 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006478 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006479
6480 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006481 touchedPoints.push_back(PointF{150, 150});
6482 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006483 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006484
chaviw9eaa22c2020-07-01 16:21:27 -07006485 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006486 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006487 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006488
chaviw9eaa22c2020-07-01 16:21:27 -07006489 // Update the transform so rotation is set for Window 2
6490 mWindow2->setWindowTransform(0, -1, 1, 0);
6491 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006492 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006493}
6494
chaviw9eaa22c2020-07-01 16:21:27 -07006495TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006496 mWindow2->setWindowScale(0.5f, 0.5f);
6497
6498 // Touch Window 1
6499 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6500 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006501 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006502
6503 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006504 touchedPoints.push_back(PointF{150, 150});
6505 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006506
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006507 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006508
6509 // Move both windows
6510 touchedPoints = {{20, 20}, {175, 175}};
6511 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6512 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6513
chaviw9eaa22c2020-07-01 16:21:27 -07006514 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006515
chaviw9eaa22c2020-07-01 16:21:27 -07006516 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006517 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006518 expectedPoints.pop_back();
6519
6520 // Touch Window 2
6521 mWindow2->setWindowTransform(0, -1, 1, 0);
6522 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006523 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006524
6525 // Move both windows
6526 touchedPoints = {{20, 20}, {175, 175}};
6527 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6528 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6529
6530 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006531}
6532
6533TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6534 mWindow1->setWindowScale(0.5f, 0.5f);
6535
6536 // Touch Window 1
6537 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6538 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006539 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006540
6541 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006542 touchedPoints.push_back(PointF{150, 150});
6543 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006544
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006545 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006546
6547 // Move both windows
6548 touchedPoints = {{20, 20}, {175, 175}};
6549 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6550 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6551
chaviw9eaa22c2020-07-01 16:21:27 -07006552 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006553}
6554
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006555/**
6556 * When one of the windows is slippery, the touch should not slip into the other window with the
6557 * same input channel.
6558 */
6559TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6560 mWindow1->setSlippery(true);
6561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6562
6563 // Touch down in window 1
6564 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6565 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6566 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6567
6568 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6569 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6570 // getting generated.
6571 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6572 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6573
6574 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6575}
6576
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006577/**
6578 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6579 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6580 * that the pointer is hovering over may have a different transform.
6581 */
6582TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6583 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6584
6585 // Start hover in window 1
6586 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6587 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6588 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6589 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6590
6591 // Move hover to window 2.
6592 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6593 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6594
6595 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6596 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6597 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6598}
6599
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006600class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6601 virtual void SetUp() override {
6602 InputDispatcherTest::SetUp();
6603
Chris Yea209fde2020-07-22 13:54:51 -07006604 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006605 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006606 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6607 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006608 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006609 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006610 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006611
6612 // Set focused application.
6613 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6614
6615 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006616 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006617 mWindow->consumeFocusEvent(true);
6618 }
6619
6620 virtual void TearDown() override {
6621 InputDispatcherTest::TearDown();
6622 mWindow.clear();
6623 }
6624
6625protected:
Chris Yea209fde2020-07-22 13:54:51 -07006626 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006627 sp<FakeWindowHandle> mWindow;
6628 static constexpr PointF WINDOW_LOCATION = {20, 20};
6629
6630 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006632 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6633 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006635 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6636 WINDOW_LOCATION));
6637 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006638
6639 sp<FakeWindowHandle> addSpyWindow() {
6640 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006641 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006642 spy->setTrustedOverlay(true);
6643 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006644 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006645 spy->setDispatchingTimeout(30ms);
6646 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6647 return spy;
6648 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006649};
6650
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006651// Send a tap and respond, which should not cause an ANR.
6652TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6653 tapOnWindow();
6654 mWindow->consumeMotionDown();
6655 mWindow->consumeMotionUp();
6656 ASSERT_TRUE(mDispatcher->waitForIdle());
6657 mFakePolicy->assertNotifyAnrWasNotCalled();
6658}
6659
6660// Send a regular key and respond, which should not cause an ANR.
6661TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006663 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6664 ASSERT_TRUE(mDispatcher->waitForIdle());
6665 mFakePolicy->assertNotifyAnrWasNotCalled();
6666}
6667
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006668TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6669 mWindow->setFocusable(false);
6670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6671 mWindow->consumeFocusEvent(false);
6672
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006673 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006674 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6675 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6676 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006678 // Key will not go to window because we have no focused window.
6679 // The 'no focused window' ANR timer should start instead.
6680
6681 // Now, the focused application goes away.
6682 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6683 // The key should get dropped and there should be no ANR.
6684
6685 ASSERT_TRUE(mDispatcher->waitForIdle());
6686 mFakePolicy->assertNotifyAnrWasNotCalled();
6687}
6688
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006689// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006690// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6691// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006692TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006694 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6695 WINDOW_LOCATION));
6696
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006697 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6698 ASSERT_TRUE(sequenceNum);
6699 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006700 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006701
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006702 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006703 mWindow->consumeMotionEvent(
6704 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006705 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006706 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006707}
6708
6709// Send a key to the app and have the app not respond right away.
6710TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6711 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006713 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6714 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006715 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006716 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006717 ASSERT_TRUE(mDispatcher->waitForIdle());
6718}
6719
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006720// We have a focused application, but no focused window
6721TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006722 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006723 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6724 mWindow->consumeFocusEvent(false);
6725
6726 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006728 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6729 WINDOW_LOCATION));
6730 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6731 mDispatcher->waitForIdle();
6732 mFakePolicy->assertNotifyAnrWasNotCalled();
6733
6734 // Once a focused event arrives, we get an ANR for this application
6735 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6736 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006737 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006738 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6739 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006740 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006741 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006742 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006743 ASSERT_TRUE(mDispatcher->waitForIdle());
6744}
6745
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006746/**
6747 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6748 * there will not be an ANR.
6749 */
6750TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6751 mWindow->setFocusable(false);
6752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6753 mWindow->consumeFocusEvent(false);
6754
6755 KeyEvent event;
6756 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6757 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6758
6759 // Define a valid key down event that is stale (too old).
6760 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6761 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006762 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006763
6764 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6765
6766 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006767 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006768 InputEventInjectionSync::WAIT_FOR_RESULT,
6769 INJECT_EVENT_TIMEOUT, policyFlags);
6770 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6771 << "Injection should fail because the event is stale";
6772
6773 ASSERT_TRUE(mDispatcher->waitForIdle());
6774 mFakePolicy->assertNotifyAnrWasNotCalled();
6775 mWindow->assertNoEvents();
6776}
6777
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006778// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006779// Make sure that we don't notify policy twice about the same ANR.
6780TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006781 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006782 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6783 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006784
6785 // Once a focused event arrives, we get an ANR for this application
6786 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6787 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006788 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006789 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6790 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006791 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006792 const std::chrono::duration appTimeout =
6793 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6794 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006795
Vishnu Naire4df8752022-09-08 09:17:55 -07006796 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006797 // ANR should not be raised again. It is up to policy to do that if it desires.
6798 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006800 // If we now get a focused window, the ANR should stop, but the policy handles that via
6801 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006802 ASSERT_TRUE(mDispatcher->waitForIdle());
6803}
6804
6805// We have a focused application, but no focused window
6806TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006807 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6809 mWindow->consumeFocusEvent(false);
6810
6811 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006812 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006813 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006814 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6815 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006816
Vishnu Naire4df8752022-09-08 09:17:55 -07006817 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6818 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006819
6820 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006821 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006822 ASSERT_TRUE(mDispatcher->waitForIdle());
6823 mWindow->assertNoEvents();
6824}
6825
6826/**
6827 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6828 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6829 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6830 * the ANR mechanism should still work.
6831 *
6832 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6833 * DOWN event, while not responding on the second one.
6834 */
6835TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6836 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6837 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6838 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6839 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6840 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006841 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006842
6843 // Now send ACTION_UP, with identical timestamp
6844 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6845 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6846 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6847 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006848 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006849
6850 // We have now sent down and up. Let's consume first event and then ANR on the second.
6851 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6852 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006853 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006854}
6855
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006856// A spy window can receive an ANR
6857TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6858 sp<FakeWindowHandle> spy = addSpyWindow();
6859
6860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6861 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6862 WINDOW_LOCATION));
6863 mWindow->consumeMotionDown();
6864
6865 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6866 ASSERT_TRUE(sequenceNum);
6867 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006868 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006869
6870 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006871 spy->consumeMotionEvent(
6872 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006873 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006874 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006875}
6876
6877// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006878// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006879TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6880 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006881
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6883 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006886
6887 // Stuck on the ACTION_UP
6888 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006889 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006890
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006891 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006892 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006893 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6894 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006895
6896 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6897 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006898 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006899 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006900 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006901}
6902
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006903// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006904// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006905TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6906 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006907
6908 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006909 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6910 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911
6912 mWindow->consumeMotionDown();
6913 // Stuck on the ACTION_UP
6914 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006915 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006916
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006917 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006918 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006919 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6920 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921
6922 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6923 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006924 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006926 spy->assertNoEvents();
6927}
6928
6929TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6930 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6931
6932 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6933
6934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6935 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6936 WINDOW_LOCATION));
6937
6938 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6939 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6940 ASSERT_TRUE(consumeSeq);
6941
Prabir Pradhanedd96402022-02-15 01:46:16 -08006942 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006943
6944 monitor.finishEvent(*consumeSeq);
6945 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6946
6947 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006948 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006949}
6950
6951// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6952// process events, you don't get an anr. When the window later becomes unresponsive again, you
6953// get an ANR again.
6954// 1. tap -> block on ACTION_UP -> receive ANR
6955// 2. consume all pending events (= queue becomes healthy again)
6956// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6957TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6958 tapOnWindow();
6959
6960 mWindow->consumeMotionDown();
6961 // Block on ACTION_UP
6962 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006963 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006964 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6965 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006966 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006967 mWindow->assertNoEvents();
6968
6969 tapOnWindow();
6970 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006971 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006972 mWindow->consumeMotionUp();
6973
6974 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006975 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006976 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006977 mWindow->assertNoEvents();
6978}
6979
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006980// If a connection remains unresponsive for a while, make sure policy is only notified once about
6981// it.
6982TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006984 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6985 WINDOW_LOCATION));
6986
6987 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006988 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006989 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006990 // 'notifyConnectionUnresponsive' should only be called once per connection
6991 mFakePolicy->assertNotifyAnrWasNotCalled();
6992 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006993 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006994 mWindow->consumeMotionEvent(
6995 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006996 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006997 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006998 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006999 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007000}
7001
7002/**
7003 * If a window is processing a motion event, and then a key event comes in, the key event should
7004 * not to to the focused window until the motion is processed.
7005 *
7006 * Warning!!!
7007 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7008 * and the injection timeout that we specify when injecting the key.
7009 * We must have the injection timeout (10ms) be smaller than
7010 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7011 *
7012 * If that value changes, this test should also change.
7013 */
7014TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7015 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7017
7018 tapOnWindow();
7019 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7020 ASSERT_TRUE(downSequenceNum);
7021 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7022 ASSERT_TRUE(upSequenceNum);
7023 // Don't finish the events yet, and send a key
7024 // Injection will "succeed" because we will eventually give up and send the key to the focused
7025 // window even if motions are still being processed. But because the injection timeout is short,
7026 // we will receive INJECTION_TIMED_OUT as the result.
7027
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007028 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007029 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007030 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7031 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007032 // Key will not be sent to the window, yet, because the window is still processing events
7033 // and the key remains pending, waiting for the touch events to be processed
7034 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7035 ASSERT_FALSE(keySequenceNum);
7036
7037 std::this_thread::sleep_for(500ms);
7038 // if we wait long enough though, dispatcher will give up, and still send the key
7039 // to the focused window, even though we have not yet finished the motion event
7040 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7041 mWindow->finishEvent(*downSequenceNum);
7042 mWindow->finishEvent(*upSequenceNum);
7043}
7044
7045/**
7046 * If a window is processing a motion event, and then a key event comes in, the key event should
7047 * not go to the focused window until the motion is processed.
7048 * If then a new motion comes in, then the pending key event should be going to the currently
7049 * focused window right away.
7050 */
7051TEST_F(InputDispatcherSingleWindowAnr,
7052 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7053 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7054 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7055
7056 tapOnWindow();
7057 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7058 ASSERT_TRUE(downSequenceNum);
7059 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7060 ASSERT_TRUE(upSequenceNum);
7061 // Don't finish the events yet, and send a key
7062 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007064 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7065 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007066 // At this point, key is still pending, and should not be sent to the application yet.
7067 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7068 ASSERT_FALSE(keySequenceNum);
7069
7070 // Now tap down again. It should cause the pending key to go to the focused window right away.
7071 tapOnWindow();
7072 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7073 // the other events yet. We can finish events in any order.
7074 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7075 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7076 mWindow->consumeMotionDown();
7077 mWindow->consumeMotionUp();
7078 mWindow->assertNoEvents();
7079}
7080
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007081/**
7082 * Send an event to the app and have the app not respond right away.
7083 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7084 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7085 * At some point, the window becomes responsive again.
7086 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7087 */
7088TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7089 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7090 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7091 .build());
7092
7093 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7094 ASSERT_TRUE(sequenceNum);
7095 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7096 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7097
7098 mWindow->finishEvent(*sequenceNum);
7099 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7100 ASSERT_TRUE(mDispatcher->waitForIdle());
7101 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7102
7103 // Now that the window is responsive, let's continue the gesture.
7104 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7105 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7106 .build());
7107
7108 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7109 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7110 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7111 .build());
7112
7113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7114 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7115 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7116 .build());
7117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7118 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7119 .build());
7120 // We already canceled this pointer, so the window shouldn't get any new events.
7121 mWindow->assertNoEvents();
7122
7123 // Start another one.
7124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7125 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7126 .build());
7127 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7128}
7129
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007130class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7131 virtual void SetUp() override {
7132 InputDispatcherTest::SetUp();
7133
Chris Yea209fde2020-07-22 13:54:51 -07007134 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007135 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007136 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7137 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007138 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007139 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007140 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007141
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007142 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7143 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007144 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007146
7147 // Set focused application.
7148 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007149 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007150
7151 // Expect one focus window exist in display.
7152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007153 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007154 mFocusedWindow->consumeFocusEvent(true);
7155 }
7156
7157 virtual void TearDown() override {
7158 InputDispatcherTest::TearDown();
7159
7160 mUnfocusedWindow.clear();
7161 mFocusedWindow.clear();
7162 }
7163
7164protected:
Chris Yea209fde2020-07-22 13:54:51 -07007165 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007166 sp<FakeWindowHandle> mUnfocusedWindow;
7167 sp<FakeWindowHandle> mFocusedWindow;
7168 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7169 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7170 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7171
7172 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7173
7174 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7175
7176private:
7177 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007179 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7180 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007182 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7183 location));
7184 }
7185};
7186
7187// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7188// should be ANR'd first.
7189TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007191 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7192 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007194 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007195 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007196 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007197 // We consumed all events, so no ANR
7198 ASSERT_TRUE(mDispatcher->waitForIdle());
7199 mFakePolicy->assertNotifyAnrWasNotCalled();
7200
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007202 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7203 FOCUSED_WINDOW_LOCATION));
7204 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7205 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007206
7207 const std::chrono::duration timeout =
7208 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007209 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007210 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7211 // sequence to make it consistent
7212 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007213 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007214 mFocusedWindow->consumeMotionDown();
7215 // This cancel is generated because the connection was unresponsive
7216 mFocusedWindow->consumeMotionCancel();
7217 mFocusedWindow->assertNoEvents();
7218 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007219 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007220 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7221 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007222 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007223}
7224
7225// If we have 2 windows with identical timeouts that are both unresponsive,
7226// it doesn't matter which order they should have ANR.
7227// But we should receive ANR for both.
7228TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7229 // Set the timeout for unfocused window to match the focused window
7230 mUnfocusedWindow->setDispatchingTimeout(10ms);
7231 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7232
7233 tapOnFocusedWindow();
7234 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007235 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7236 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7237 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007238
7239 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007240 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7241 mFocusedWindow->getToken() == anrConnectionToken2);
7242 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7243 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007244
7245 ASSERT_TRUE(mDispatcher->waitForIdle());
7246 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007247
7248 mFocusedWindow->consumeMotionDown();
7249 mFocusedWindow->consumeMotionUp();
7250 mUnfocusedWindow->consumeMotionOutside();
7251
Prabir Pradhanedd96402022-02-15 01:46:16 -08007252 sp<IBinder> responsiveToken1, responsiveToken2;
7253 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7254 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007255
7256 // Both applications should be marked as responsive, in any order
7257 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7258 mFocusedWindow->getToken() == responsiveToken2);
7259 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7260 mUnfocusedWindow->getToken() == responsiveToken2);
7261 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007262}
7263
7264// If a window is already not responding, the second tap on the same window should be ignored.
7265// We should also log an error to account for the dropped event (not tested here).
7266// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7267TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7268 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007269 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007270 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007271 // Receive the events, but don't respond
7272 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7273 ASSERT_TRUE(downEventSequenceNum);
7274 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7275 ASSERT_TRUE(upEventSequenceNum);
7276 const std::chrono::duration timeout =
7277 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007278 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007279
7280 // Tap once again
7281 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007282 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007283 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7284 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007285 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007286 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7287 FOCUSED_WINDOW_LOCATION));
7288 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7289 // valid touch target
7290 mUnfocusedWindow->assertNoEvents();
7291
7292 // Consume the first tap
7293 mFocusedWindow->finishEvent(*downEventSequenceNum);
7294 mFocusedWindow->finishEvent(*upEventSequenceNum);
7295 ASSERT_TRUE(mDispatcher->waitForIdle());
7296 // The second tap did not go to the focused window
7297 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007298 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007299 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7300 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007301 mFakePolicy->assertNotifyAnrWasNotCalled();
7302}
7303
7304// If you tap outside of all windows, there will not be ANR
7305TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007306 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007307 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7308 LOCATION_OUTSIDE_ALL_WINDOWS));
7309 ASSERT_TRUE(mDispatcher->waitForIdle());
7310 mFakePolicy->assertNotifyAnrWasNotCalled();
7311}
7312
7313// Since the focused window is paused, tapping on it should not produce any events
7314TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7315 mFocusedWindow->setPaused(true);
7316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7317
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007318 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007319 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7320 FOCUSED_WINDOW_LOCATION));
7321
7322 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7323 ASSERT_TRUE(mDispatcher->waitForIdle());
7324 // Should not ANR because the window is paused, and touches shouldn't go to it
7325 mFakePolicy->assertNotifyAnrWasNotCalled();
7326
7327 mFocusedWindow->assertNoEvents();
7328 mUnfocusedWindow->assertNoEvents();
7329}
7330
7331/**
7332 * If a window is processing a motion event, and then a key event comes in, the key event should
7333 * not to to the focused window until the motion is processed.
7334 * If a different window becomes focused at this time, the key should go to that window instead.
7335 *
7336 * Warning!!!
7337 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7338 * and the injection timeout that we specify when injecting the key.
7339 * We must have the injection timeout (10ms) be smaller than
7340 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7341 *
7342 * If that value changes, this test should also change.
7343 */
7344TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7345 // Set a long ANR timeout to prevent it from triggering
7346 mFocusedWindow->setDispatchingTimeout(2s);
7347 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7348
7349 tapOnUnfocusedWindow();
7350 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7351 ASSERT_TRUE(downSequenceNum);
7352 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7353 ASSERT_TRUE(upSequenceNum);
7354 // Don't finish the events yet, and send a key
7355 // Injection will succeed because we will eventually give up and send the key to the focused
7356 // window even if motions are still being processed.
7357
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007358 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007359 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7360 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007362 // Key will not be sent to the window, yet, because the window is still processing events
7363 // and the key remains pending, waiting for the touch events to be processed
7364 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7365 ASSERT_FALSE(keySequenceNum);
7366
7367 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007368 mFocusedWindow->setFocusable(false);
7369 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007370 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007371 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007372
7373 // Focus events should precede the key events
7374 mUnfocusedWindow->consumeFocusEvent(true);
7375 mFocusedWindow->consumeFocusEvent(false);
7376
7377 // Finish the tap events, which should unblock dispatcher
7378 mUnfocusedWindow->finishEvent(*downSequenceNum);
7379 mUnfocusedWindow->finishEvent(*upSequenceNum);
7380
7381 // Now that all queues are cleared and no backlog in the connections, the key event
7382 // can finally go to the newly focused "mUnfocusedWindow".
7383 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7384 mFocusedWindow->assertNoEvents();
7385 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007386 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007387}
7388
7389// When the touch stream is split across 2 windows, and one of them does not respond,
7390// then ANR should be raised and the touch should be canceled for the unresponsive window.
7391// The other window should not be affected by that.
7392TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7393 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007394 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7395 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7396 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007397 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007398 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007399
7400 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007401 mDispatcher->notifyMotion(
7402 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7403 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007404
7405 const std::chrono::duration timeout =
7406 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007407 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007408
7409 mUnfocusedWindow->consumeMotionDown();
7410 mFocusedWindow->consumeMotionDown();
7411 // Focused window may or may not receive ACTION_MOVE
7412 // But it should definitely receive ACTION_CANCEL due to the ANR
7413 InputEvent* event;
7414 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7415 ASSERT_TRUE(moveOrCancelSequenceNum);
7416 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7417 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007418 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007419 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7420 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7421 mFocusedWindow->consumeMotionCancel();
7422 } else {
7423 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7424 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007425 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007426 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7427 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007428
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007429 mUnfocusedWindow->assertNoEvents();
7430 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007431 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007432}
7433
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007434/**
7435 * If we have no focused window, and a key comes in, we start the ANR timer.
7436 * The focused application should add a focused window before the timer runs out to prevent ANR.
7437 *
7438 * If the user touches another application during this time, the key should be dropped.
7439 * Next, if a new focused window comes in, without toggling the focused application,
7440 * then no ANR should occur.
7441 *
7442 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7443 * but in some cases the policy may not update the focused application.
7444 */
7445TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7446 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7447 std::make_shared<FakeApplicationHandle>();
7448 focusedApplication->setDispatchingTimeout(60ms);
7449 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7450 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7451 mFocusedWindow->setFocusable(false);
7452
7453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7454 mFocusedWindow->consumeFocusEvent(false);
7455
7456 // Send a key. The ANR timer should start because there is no focused window.
7457 // 'focusedApplication' will get blamed if this timer completes.
7458 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007459 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007460 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7461 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7462 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007464
7465 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7466 // then the injected touches won't cause the focused event to get dropped.
7467 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7468 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7469 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7470 // For this test, it means that the key would get delivered to the window once it becomes
7471 // focused.
7472 std::this_thread::sleep_for(10ms);
7473
7474 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007475 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7476 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7477 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007478
7479 // We do not consume the motion right away, because that would require dispatcher to first
7480 // process (== drop) the key event, and by that time, ANR will be raised.
7481 // Set the focused window first.
7482 mFocusedWindow->setFocusable(true);
7483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7484 setFocusedWindow(mFocusedWindow);
7485 mFocusedWindow->consumeFocusEvent(true);
7486 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7487 // to another application. This could be a bug / behaviour in the policy.
7488
7489 mUnfocusedWindow->consumeMotionDown();
7490
7491 ASSERT_TRUE(mDispatcher->waitForIdle());
7492 // Should not ANR because we actually have a focused window. It was just added too slowly.
7493 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7494}
7495
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007496// These tests ensure we cannot send touch events to a window that's positioned behind a window
7497// that has feature NO_INPUT_CHANNEL.
7498// Layout:
7499// Top (closest to user)
7500// mNoInputWindow (above all windows)
7501// mBottomWindow
7502// Bottom (furthest from user)
7503class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7504 virtual void SetUp() override {
7505 InputDispatcherTest::SetUp();
7506
7507 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007508 mNoInputWindow =
7509 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7510 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007511 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007512 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007513 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7514 // It's perfectly valid for this window to not have an associated input channel
7515
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007516 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7517 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007518 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7519
7520 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7521 }
7522
7523protected:
7524 std::shared_ptr<FakeApplicationHandle> mApplication;
7525 sp<FakeWindowHandle> mNoInputWindow;
7526 sp<FakeWindowHandle> mBottomWindow;
7527};
7528
7529TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7530 PointF touchedPoint = {10, 10};
7531
Prabir Pradhan678438e2023-04-13 19:32:51 +00007532 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7533 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7534 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007535
7536 mNoInputWindow->assertNoEvents();
7537 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7538 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7539 // and therefore should prevent mBottomWindow from receiving touches
7540 mBottomWindow->assertNoEvents();
7541}
7542
7543/**
7544 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7545 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7546 */
7547TEST_F(InputDispatcherMultiWindowOcclusionTests,
7548 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007549 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7550 "Window with input channel and NO_INPUT_CHANNEL",
7551 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007552
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007553 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007554 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7556
7557 PointF touchedPoint = {10, 10};
7558
Prabir Pradhan678438e2023-04-13 19:32:51 +00007559 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7560 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7561 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007562
7563 mNoInputWindow->assertNoEvents();
7564 mBottomWindow->assertNoEvents();
7565}
7566
Vishnu Nair958da932020-08-21 17:12:37 -07007567class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7568protected:
7569 std::shared_ptr<FakeApplicationHandle> mApp;
7570 sp<FakeWindowHandle> mWindow;
7571 sp<FakeWindowHandle> mMirror;
7572
7573 virtual void SetUp() override {
7574 InputDispatcherTest::SetUp();
7575 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007576 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7577 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7578 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007579 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7580 mWindow->setFocusable(true);
7581 mMirror->setFocusable(true);
7582 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7583 }
7584};
7585
7586TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7587 // Request focus on a mirrored window
7588 setFocusedWindow(mMirror);
7589
7590 // window gets focused
7591 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7593 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007594 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7595}
7596
7597// A focused & mirrored window remains focused only if the window and its mirror are both
7598// focusable.
7599TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7600 setFocusedWindow(mMirror);
7601
7602 // window gets focused
7603 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7605 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007606 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7608 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007609 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7610
7611 mMirror->setFocusable(false);
7612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7613
7614 // window loses focus since one of the windows associated with the token in not focusable
7615 mWindow->consumeFocusEvent(false);
7616
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007617 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7618 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007619 mWindow->assertNoEvents();
7620}
7621
7622// A focused & mirrored window remains focused until the window and its mirror both become
7623// invisible.
7624TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7625 setFocusedWindow(mMirror);
7626
7627 // window gets focused
7628 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7630 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007631 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7633 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007634 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7635
7636 mMirror->setVisible(false);
7637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7638
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7640 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007641 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7643 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007644 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7645
7646 mWindow->setVisible(false);
7647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7648
7649 // window loses focus only after all windows associated with the token become invisible.
7650 mWindow->consumeFocusEvent(false);
7651
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007652 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7653 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007654 mWindow->assertNoEvents();
7655}
7656
7657// A focused & mirrored window remains focused until both windows are removed.
7658TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
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 // single window is removed but the window token remains focused
7671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {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 // Both windows are removed
7681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7682 mWindow->consumeFocusEvent(false);
7683
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007684 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7685 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007686 mWindow->assertNoEvents();
7687}
7688
7689// Focus request can be pending until one window becomes visible.
7690TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7691 // Request focus on an invisible mirror.
7692 mWindow->setVisible(false);
7693 mMirror->setVisible(false);
7694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7695 setFocusedWindow(mMirror);
7696
7697 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007699 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7700 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007701
7702 mMirror->setVisible(true);
7703 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7704
7705 // window gets focused
7706 mWindow->consumeFocusEvent(true);
7707 // window gets the pending key event
7708 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7709}
Prabir Pradhan99987712020-11-10 18:43:05 -08007710
7711class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7712protected:
7713 std::shared_ptr<FakeApplicationHandle> mApp;
7714 sp<FakeWindowHandle> mWindow;
7715 sp<FakeWindowHandle> mSecondWindow;
7716
7717 void SetUp() override {
7718 InputDispatcherTest::SetUp();
7719 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007720 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007721 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007722 mSecondWindow =
7723 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007724 mSecondWindow->setFocusable(true);
7725
7726 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7728
7729 setFocusedWindow(mWindow);
7730 mWindow->consumeFocusEvent(true);
7731 }
7732
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007733 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007734 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007735 }
7736
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007737 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7738 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007739 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007740 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7741 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007742 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007743 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007744 }
7745};
7746
7747TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7748 // Ensure that capture cannot be obtained for unfocused windows.
7749 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7750 mFakePolicy->assertSetPointerCaptureNotCalled();
7751 mSecondWindow->assertNoEvents();
7752
7753 // Ensure that capture can be enabled from the focus window.
7754 requestAndVerifyPointerCapture(mWindow, true);
7755
7756 // Ensure that capture cannot be disabled from a window that does not have capture.
7757 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7758 mFakePolicy->assertSetPointerCaptureNotCalled();
7759
7760 // Ensure that capture can be disabled from the window with capture.
7761 requestAndVerifyPointerCapture(mWindow, false);
7762}
7763
7764TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007765 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007766
7767 setFocusedWindow(mSecondWindow);
7768
7769 // Ensure that the capture disabled event was sent first.
7770 mWindow->consumeCaptureEvent(false);
7771 mWindow->consumeFocusEvent(false);
7772 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007773 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007774
7775 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007776 notifyPointerCaptureChanged({});
7777 notifyPointerCaptureChanged(request);
7778 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007779 mWindow->assertNoEvents();
7780 mSecondWindow->assertNoEvents();
7781 mFakePolicy->assertSetPointerCaptureNotCalled();
7782}
7783
7784TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007785 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007786
7787 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007788 notifyPointerCaptureChanged({});
7789 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007790
7791 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007792 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007793 mWindow->consumeCaptureEvent(false);
7794 mWindow->assertNoEvents();
7795}
7796
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007797TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7798 requestAndVerifyPointerCapture(mWindow, true);
7799
7800 // The first window loses focus.
7801 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007802 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007803 mWindow->consumeCaptureEvent(false);
7804
7805 // Request Pointer Capture from the second window before the notification from InputReader
7806 // arrives.
7807 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007808 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007809
7810 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007811 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007812
7813 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007814 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007815
7816 mSecondWindow->consumeFocusEvent(true);
7817 mSecondWindow->consumeCaptureEvent(true);
7818}
7819
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007820TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7821 // App repeatedly enables and disables capture.
7822 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7823 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7824 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7825 mFakePolicy->assertSetPointerCaptureCalled(false);
7826 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7827 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7828
7829 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7830 // first request is now stale, this should do nothing.
7831 notifyPointerCaptureChanged(firstRequest);
7832 mWindow->assertNoEvents();
7833
7834 // InputReader notifies that the second request was enabled.
7835 notifyPointerCaptureChanged(secondRequest);
7836 mWindow->consumeCaptureEvent(true);
7837}
7838
Prabir Pradhan7092e262022-05-03 16:51:09 +00007839TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7840 requestAndVerifyPointerCapture(mWindow, true);
7841
7842 // App toggles pointer capture off and on.
7843 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7844 mFakePolicy->assertSetPointerCaptureCalled(false);
7845
7846 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7847 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7848
7849 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7850 // preceding "disable" request.
7851 notifyPointerCaptureChanged(enableRequest);
7852
7853 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7854 // any notifications.
7855 mWindow->assertNoEvents();
7856}
7857
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007858class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7859protected:
7860 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007861
7862 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7863 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7864
7865 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7866 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7867
7868 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7869 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7870 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7871 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7872 MAXIMUM_OBSCURING_OPACITY);
7873
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007874 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7875 static constexpr gui::Uid APP_B_UID{10002};
7876 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007877
7878 sp<FakeWindowHandle> mTouchWindow;
7879
7880 virtual void SetUp() override {
7881 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007882 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007883 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7884 }
7885
7886 virtual void TearDown() override {
7887 InputDispatcherTest::TearDown();
7888 mTouchWindow.clear();
7889 }
7890
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007891 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007892 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007893 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007894 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007895 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007896 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007897 return window;
7898 }
7899
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007900 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007901 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7902 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007903 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007904 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007905 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007906 return window;
7907 }
7908
7909 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007910 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7911 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7912 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007913 }
7914};
7915
7916TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007917 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007918 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007920
7921 touch();
7922
7923 mTouchWindow->assertNoEvents();
7924}
7925
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007926TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007927 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7928 const sp<FakeWindowHandle>& w =
7929 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7930 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7931
7932 touch();
7933
7934 mTouchWindow->assertNoEvents();
7935}
7936
7937TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007938 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7939 const sp<FakeWindowHandle>& w =
7940 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7942
7943 touch();
7944
7945 w->assertNoEvents();
7946}
7947
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007948TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007949 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007951
7952 touch();
7953
7954 mTouchWindow->consumeAnyMotionDown();
7955}
7956
7957TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007958 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007959 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007960 w->setFrame(Rect(0, 0, 50, 50));
7961 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007962
7963 touch({PointF{100, 100}});
7964
7965 mTouchWindow->consumeAnyMotionDown();
7966}
7967
7968TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007969 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007970 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7972
7973 touch();
7974
7975 mTouchWindow->consumeAnyMotionDown();
7976}
7977
7978TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7979 const sp<FakeWindowHandle>& w =
7980 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7981 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007982
7983 touch();
7984
7985 mTouchWindow->consumeAnyMotionDown();
7986}
7987
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007988TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7989 const sp<FakeWindowHandle>& w =
7990 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7992
7993 touch();
7994
7995 w->assertNoEvents();
7996}
7997
7998/**
7999 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8000 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8001 * window, the occluding window will still receive ACTION_OUTSIDE event.
8002 */
8003TEST_F(InputDispatcherUntrustedTouchesTest,
8004 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8005 const sp<FakeWindowHandle>& w =
8006 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008007 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8009
8010 touch();
8011
8012 w->consumeMotionOutside();
8013}
8014
8015TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8016 const sp<FakeWindowHandle>& w =
8017 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008018 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008019 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8020
8021 touch();
8022
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008023 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008024}
8025
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008026TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008027 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008028 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8029 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008030 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8031
8032 touch();
8033
8034 mTouchWindow->consumeAnyMotionDown();
8035}
8036
8037TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8038 const sp<FakeWindowHandle>& w =
8039 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8040 MAXIMUM_OBSCURING_OPACITY);
8041 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008042
8043 touch();
8044
8045 mTouchWindow->consumeAnyMotionDown();
8046}
8047
8048TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008049 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008050 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8051 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8053
8054 touch();
8055
8056 mTouchWindow->assertNoEvents();
8057}
8058
8059TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8060 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8061 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008062 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8063 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008064 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008065 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8066 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008067 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8068
8069 touch();
8070
8071 mTouchWindow->assertNoEvents();
8072}
8073
8074TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8075 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8076 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008077 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8078 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008079 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008080 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8081 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8083
8084 touch();
8085
8086 mTouchWindow->consumeAnyMotionDown();
8087}
8088
8089TEST_F(InputDispatcherUntrustedTouchesTest,
8090 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8091 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008092 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8093 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008094 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008095 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8096 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008097 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8098
8099 touch();
8100
8101 mTouchWindow->consumeAnyMotionDown();
8102}
8103
8104TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8105 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008106 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8107 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008108 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008109 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8110 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008111 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008112
8113 touch();
8114
8115 mTouchWindow->assertNoEvents();
8116}
8117
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008118TEST_F(InputDispatcherUntrustedTouchesTest,
8119 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8120 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008121 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8122 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008123 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008124 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8125 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008126 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8127
8128 touch();
8129
8130 mTouchWindow->assertNoEvents();
8131}
8132
8133TEST_F(InputDispatcherUntrustedTouchesTest,
8134 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8135 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008136 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8137 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008138 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008139 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8140 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008141 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8142
8143 touch();
8144
8145 mTouchWindow->consumeAnyMotionDown();
8146}
8147
8148TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8149 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008150 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8151 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8153
8154 touch();
8155
8156 mTouchWindow->consumeAnyMotionDown();
8157}
8158
8159TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8160 const sp<FakeWindowHandle>& w =
8161 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8163
8164 touch();
8165
8166 mTouchWindow->consumeAnyMotionDown();
8167}
8168
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008169TEST_F(InputDispatcherUntrustedTouchesTest,
8170 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8171 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8172 const sp<FakeWindowHandle>& w =
8173 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8175
8176 touch();
8177
8178 mTouchWindow->assertNoEvents();
8179}
8180
8181TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8182 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8183 const sp<FakeWindowHandle>& w =
8184 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8186
8187 touch();
8188
8189 mTouchWindow->consumeAnyMotionDown();
8190}
8191
8192TEST_F(InputDispatcherUntrustedTouchesTest,
8193 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8194 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8195 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008196 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8197 OPACITY_ABOVE_THRESHOLD);
8198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8199
8200 touch();
8201
8202 mTouchWindow->consumeAnyMotionDown();
8203}
8204
8205TEST_F(InputDispatcherUntrustedTouchesTest,
8206 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8207 const sp<FakeWindowHandle>& w1 =
8208 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8209 OPACITY_BELOW_THRESHOLD);
8210 const sp<FakeWindowHandle>& w2 =
8211 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8212 OPACITY_BELOW_THRESHOLD);
8213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8214
8215 touch();
8216
8217 mTouchWindow->assertNoEvents();
8218}
8219
8220/**
8221 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8222 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8223 * (which alone would result in allowing touches) does not affect the blocking behavior.
8224 */
8225TEST_F(InputDispatcherUntrustedTouchesTest,
8226 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8227 const sp<FakeWindowHandle>& wB =
8228 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8229 OPACITY_BELOW_THRESHOLD);
8230 const sp<FakeWindowHandle>& wC =
8231 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8232 OPACITY_BELOW_THRESHOLD);
8233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8234
8235 touch();
8236
8237 mTouchWindow->assertNoEvents();
8238}
8239
8240/**
8241 * This test is testing that a window from a different UID but with same application token doesn't
8242 * block the touch. Apps can share the application token for close UI collaboration for example.
8243 */
8244TEST_F(InputDispatcherUntrustedTouchesTest,
8245 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8246 const sp<FakeWindowHandle>& w =
8247 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8248 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008249 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8250
8251 touch();
8252
8253 mTouchWindow->consumeAnyMotionDown();
8254}
8255
arthurhungb89ccb02020-12-30 16:19:01 +08008256class InputDispatcherDragTests : public InputDispatcherTest {
8257protected:
8258 std::shared_ptr<FakeApplicationHandle> mApp;
8259 sp<FakeWindowHandle> mWindow;
8260 sp<FakeWindowHandle> mSecondWindow;
8261 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008262 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008263 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8264 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008265
8266 void SetUp() override {
8267 InputDispatcherTest::SetUp();
8268 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008269 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008270 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008271
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008272 mSecondWindow =
8273 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008274 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008275
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008276 mSpyWindow =
8277 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008278 mSpyWindow->setSpy(true);
8279 mSpyWindow->setTrustedOverlay(true);
8280 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8281
arthurhungb89ccb02020-12-30 16:19:01 +08008282 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008284 }
8285
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008286 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8287 switch (fromSource) {
8288 case AINPUT_SOURCE_TOUCHSCREEN:
8289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8290 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8291 ADISPLAY_ID_DEFAULT, {50, 50}))
8292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8293 break;
8294 case AINPUT_SOURCE_STYLUS:
8295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8296 injectMotionEvent(
8297 mDispatcher,
8298 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8299 AINPUT_SOURCE_STYLUS)
8300 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008301 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008302 .x(50)
8303 .y(50))
8304 .build()));
8305 break;
8306 case AINPUT_SOURCE_MOUSE:
8307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8308 injectMotionEvent(
8309 mDispatcher,
8310 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8311 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8312 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008313 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008314 .x(50)
8315 .y(50))
8316 .build()));
8317 break;
8318 default:
8319 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8320 }
arthurhungb89ccb02020-12-30 16:19:01 +08008321
8322 // Window should receive motion event.
8323 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008324 // Spy window should also receive motion event
8325 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008326 }
8327
8328 // Start performing drag, we will create a drag window and transfer touch to it.
8329 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8330 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008331 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008332 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008333 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008334 }
arthurhungb89ccb02020-12-30 16:19:01 +08008335
8336 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008337 mDragWindow =
8338 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008339 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008340 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008341 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008342
8343 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008344 bool transferred =
8345 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008346 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008347 if (transferred) {
8348 mWindow->consumeMotionCancel();
8349 mDragWindow->consumeMotionDown();
8350 }
8351 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008352 }
8353};
8354
8355TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008356 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008357
8358 // Move on window.
8359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8360 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8361 ADISPLAY_ID_DEFAULT, {50, 50}))
8362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8363 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8364 mWindow->consumeDragEvent(false, 50, 50);
8365 mSecondWindow->assertNoEvents();
8366
8367 // Move to another window.
8368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8369 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8370 ADISPLAY_ID_DEFAULT, {150, 50}))
8371 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8372 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8373 mWindow->consumeDragEvent(true, 150, 50);
8374 mSecondWindow->consumeDragEvent(false, 50, 50);
8375
8376 // Move back to original window.
8377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8378 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8379 ADISPLAY_ID_DEFAULT, {50, 50}))
8380 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8381 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8382 mWindow->consumeDragEvent(false, 50, 50);
8383 mSecondWindow->consumeDragEvent(true, -50, 50);
8384
8385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8386 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8388 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8389 mWindow->assertNoEvents();
8390 mSecondWindow->assertNoEvents();
8391}
8392
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008393TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008394 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008395
8396 // No cancel event after drag start
8397 mSpyWindow->assertNoEvents();
8398
8399 const MotionEvent secondFingerDownEvent =
8400 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8401 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008402 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8403 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008404 .build();
8405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8406 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8407 InputEventInjectionSync::WAIT_FOR_RESULT))
8408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8409
8410 // Receives cancel for first pointer after next pointer down
8411 mSpyWindow->consumeMotionCancel();
8412 mSpyWindow->consumeMotionDown();
8413
8414 mSpyWindow->assertNoEvents();
8415}
8416
arthurhungf452d0b2021-01-06 00:19:52 +08008417TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008418 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008419
8420 // Move on window.
8421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8422 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8423 ADISPLAY_ID_DEFAULT, {50, 50}))
8424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8425 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8426 mWindow->consumeDragEvent(false, 50, 50);
8427 mSecondWindow->assertNoEvents();
8428
8429 // Move to another window.
8430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8431 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8432 ADISPLAY_ID_DEFAULT, {150, 50}))
8433 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8434 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8435 mWindow->consumeDragEvent(true, 150, 50);
8436 mSecondWindow->consumeDragEvent(false, 50, 50);
8437
8438 // drop to another window.
8439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8440 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8441 {150, 50}))
8442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8443 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8444 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8445 mWindow->assertNoEvents();
8446 mSecondWindow->assertNoEvents();
8447}
8448
arthurhung6d4bed92021-03-17 11:59:33 +08008449TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008450 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008451
8452 // Move on window and keep button pressed.
8453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8454 injectMotionEvent(mDispatcher,
8455 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8456 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008457 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008458 .build()))
8459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8460 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8461 mWindow->consumeDragEvent(false, 50, 50);
8462 mSecondWindow->assertNoEvents();
8463
8464 // Move to another window and release button, expect to drop item.
8465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8466 injectMotionEvent(mDispatcher,
8467 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8468 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008469 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008470 .build()))
8471 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8472 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8473 mWindow->assertNoEvents();
8474 mSecondWindow->assertNoEvents();
8475 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8476
8477 // nothing to the window.
8478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8479 injectMotionEvent(mDispatcher,
8480 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8481 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008482 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008483 .build()))
8484 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8485 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8486 mWindow->assertNoEvents();
8487 mSecondWindow->assertNoEvents();
8488}
8489
Arthur Hung54745652022-04-20 07:17:41 +00008490TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008491 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008492
8493 // Set second window invisible.
8494 mSecondWindow->setVisible(false);
8495 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8496
8497 // Move on window.
8498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8499 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8500 ADISPLAY_ID_DEFAULT, {50, 50}))
8501 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8502 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8503 mWindow->consumeDragEvent(false, 50, 50);
8504 mSecondWindow->assertNoEvents();
8505
8506 // Move to another window.
8507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8508 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8509 ADISPLAY_ID_DEFAULT, {150, 50}))
8510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8511 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8512 mWindow->consumeDragEvent(true, 150, 50);
8513 mSecondWindow->assertNoEvents();
8514
8515 // drop to another window.
8516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8517 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8518 {150, 50}))
8519 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8520 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8521 mFakePolicy->assertDropTargetEquals(nullptr);
8522 mWindow->assertNoEvents();
8523 mSecondWindow->assertNoEvents();
8524}
8525
Arthur Hung54745652022-04-20 07:17:41 +00008526TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008527 // Ensure window could track pointerIds if it didn't support split touch.
8528 mWindow->setPreventSplitting(true);
8529
Arthur Hung54745652022-04-20 07:17:41 +00008530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8531 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8532 {50, 50}))
8533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8534 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8535
8536 const MotionEvent secondFingerDownEvent =
8537 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8538 .displayId(ADISPLAY_ID_DEFAULT)
8539 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008540 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8541 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008542 .build();
8543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8544 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8545 InputEventInjectionSync::WAIT_FOR_RESULT))
8546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008547 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008548
8549 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008550 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008551}
8552
8553TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8554 // First down on second window.
8555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8556 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8557 {150, 50}))
8558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8559
8560 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8561
8562 // Second down on first window.
8563 const MotionEvent secondFingerDownEvent =
8564 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8565 .displayId(ADISPLAY_ID_DEFAULT)
8566 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008567 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8568 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008569 .build();
8570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8571 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8572 InputEventInjectionSync::WAIT_FOR_RESULT))
8573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8574 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8575
8576 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008577 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008578
8579 // Move on window.
8580 const MotionEvent secondFingerMoveEvent =
8581 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8582 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008583 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8584 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008585 .build();
8586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8587 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8588 InputEventInjectionSync::WAIT_FOR_RESULT));
8589 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8590 mWindow->consumeDragEvent(false, 50, 50);
8591 mSecondWindow->consumeMotionMove();
8592
8593 // Release the drag pointer should perform drop.
8594 const MotionEvent secondFingerUpEvent =
8595 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8596 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008597 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8598 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008599 .build();
8600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8601 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8602 InputEventInjectionSync::WAIT_FOR_RESULT));
8603 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8604 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8605 mWindow->assertNoEvents();
8606 mSecondWindow->consumeMotionMove();
8607}
8608
Arthur Hung3915c1f2022-05-31 07:17:17 +00008609TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008610 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008611
8612 // Update window of second display.
8613 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008614 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008615 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8616
8617 // Let second display has a touch state.
8618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8619 injectMotionEvent(mDispatcher,
8620 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8621 AINPUT_SOURCE_TOUCHSCREEN)
8622 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008623 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008624 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008625 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008626 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008627 // Update window again.
8628 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8629
8630 // Move on window.
8631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8632 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8633 ADISPLAY_ID_DEFAULT, {50, 50}))
8634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8635 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8636 mWindow->consumeDragEvent(false, 50, 50);
8637 mSecondWindow->assertNoEvents();
8638
8639 // Move to another window.
8640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8641 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8642 ADISPLAY_ID_DEFAULT, {150, 50}))
8643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8644 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8645 mWindow->consumeDragEvent(true, 150, 50);
8646 mSecondWindow->consumeDragEvent(false, 50, 50);
8647
8648 // drop to another window.
8649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8650 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8651 {150, 50}))
8652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8653 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8654 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8655 mWindow->assertNoEvents();
8656 mSecondWindow->assertNoEvents();
8657}
8658
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008659TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8660 startDrag(true, AINPUT_SOURCE_MOUSE);
8661 // Move on window.
8662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8663 injectMotionEvent(mDispatcher,
8664 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8665 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8666 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008667 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008668 .x(50)
8669 .y(50))
8670 .build()))
8671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8672 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8673 mWindow->consumeDragEvent(false, 50, 50);
8674 mSecondWindow->assertNoEvents();
8675
8676 // Move to another window.
8677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8678 injectMotionEvent(mDispatcher,
8679 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8680 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8681 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008682 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008683 .x(150)
8684 .y(50))
8685 .build()))
8686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8687 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8688 mWindow->consumeDragEvent(true, 150, 50);
8689 mSecondWindow->consumeDragEvent(false, 50, 50);
8690
8691 // drop to another window.
8692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8693 injectMotionEvent(mDispatcher,
8694 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8695 .buttonState(0)
8696 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008697 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008698 .x(150)
8699 .y(50))
8700 .build()))
8701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8702 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8703 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8704 mWindow->assertNoEvents();
8705 mSecondWindow->assertNoEvents();
8706}
8707
Vishnu Nair062a8672021-09-03 16:07:44 -07008708class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8709
8710TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008712 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8713 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008714 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008715 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8716 window->setFocusable(true);
8717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8718 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008719 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008720
8721 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008722 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008723 window->assertNoEvents();
8724
Prabir Pradhan678438e2023-04-13 19:32:51 +00008725 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8726 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008727 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8728 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008729 window->assertNoEvents();
8730
8731 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008732 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8734
Prabir Pradhan678438e2023-04-13 19:32:51 +00008735 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008736 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8737
Prabir Pradhan678438e2023-04-13 19:32:51 +00008738 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8739 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008740 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8741 window->assertNoEvents();
8742}
8743
8744TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8745 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8746 std::make_shared<FakeApplicationHandle>();
8747 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008748 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8749 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008750 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008751 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008752 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8755 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008756 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008757 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008758 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8759 window->setFocusable(true);
8760 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8761 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008762 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008763
8764 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008765 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008766 window->assertNoEvents();
8767
Prabir Pradhan678438e2023-04-13 19:32:51 +00008768 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8769 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008770 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8771 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008772 window->assertNoEvents();
8773
8774 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008775 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008776 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8777
Prabir Pradhan678438e2023-04-13 19:32:51 +00008778 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008779 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8780
Prabir Pradhan678438e2023-04-13 19:32:51 +00008781 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8782 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008783 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8784 window->assertNoEvents();
8785}
8786
8787TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8788 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8789 std::make_shared<FakeApplicationHandle>();
8790 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008791 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8792 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008793 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008794 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008795 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8798 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008799 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008800 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008801 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8802 window->setFocusable(true);
8803 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8804 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008805 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008806
8807 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008808 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008809 window->assertNoEvents();
8810
Prabir Pradhan678438e2023-04-13 19:32:51 +00008811 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8812 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008813 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8814 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008815 window->assertNoEvents();
8816
8817 // When the window is no longer obscured because it went on top, it should get input
8818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8819
Prabir Pradhan678438e2023-04-13 19:32:51 +00008820 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008821 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8822
Prabir Pradhan678438e2023-04-13 19:32:51 +00008823 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8824 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008825 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8826 window->assertNoEvents();
8827}
8828
Antonio Kantekf16f2832021-09-28 04:39:20 +00008829class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8830protected:
8831 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008832 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008833 sp<FakeWindowHandle> mWindow;
8834 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008835 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008836
8837 void SetUp() override {
8838 InputDispatcherTest::SetUp();
8839
8840 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008841 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008842 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008843 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008844 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008845 mSecondWindow =
8846 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008847 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008848 mThirdWindow =
8849 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8850 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8851 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008852
8853 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8855 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8856 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008857 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008858
Antonio Kantek15beb512022-06-13 22:35:41 +00008859 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008860 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008861 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008862 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8863 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008864 mThirdWindow->assertNoEvents();
8865 }
8866
8867 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8868 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008869 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008870 SECOND_DISPLAY_ID)) {
8871 mWindow->assertNoEvents();
8872 mSecondWindow->assertNoEvents();
8873 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008874 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008875 }
8876
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008877 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008878 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008879 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8880 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008881 mWindow->consumeTouchModeEvent(inTouchMode);
8882 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008883 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008884 }
8885};
8886
Antonio Kantek26defcf2022-02-08 01:12:27 +00008887TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008888 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008889 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8890 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008891 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008892}
8893
Antonio Kantek26defcf2022-02-08 01:12:27 +00008894TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8895 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008896 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008897 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008898 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008899 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008900 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008901 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008902 mWindow->assertNoEvents();
8903 mSecondWindow->assertNoEvents();
8904}
8905
8906TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8907 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008908 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008909 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008910 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008911 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008912 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008913}
8914
Antonio Kantekf16f2832021-09-28 04:39:20 +00008915TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008916 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008917 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8918 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008919 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008920 mWindow->assertNoEvents();
8921 mSecondWindow->assertNoEvents();
8922}
8923
Antonio Kantek15beb512022-06-13 22:35:41 +00008924TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8925 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8926 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8927 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008928 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008929 mWindow->assertNoEvents();
8930 mSecondWindow->assertNoEvents();
8931 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8932}
8933
Antonio Kantek48710e42022-03-24 14:19:30 -07008934TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8935 // Interact with the window first.
8936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8937 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8938 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8939
8940 // Then remove focus.
8941 mWindow->setFocusable(false);
8942 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8943
8944 // Assert that caller can switch touch mode by owning one of the last interacted window.
8945 const WindowInfo& windowInfo = *mWindow->getInfo();
8946 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8947 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008948 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008949}
8950
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008951class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8952public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008953 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008954 std::shared_ptr<FakeApplicationHandle> application =
8955 std::make_shared<FakeApplicationHandle>();
8956 std::string name = "Fake Spy ";
8957 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008958 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8959 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008960 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008961 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008962 return spy;
8963 }
8964
8965 sp<FakeWindowHandle> createForeground() {
8966 std::shared_ptr<FakeApplicationHandle> application =
8967 std::make_shared<FakeApplicationHandle>();
8968 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008969 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8970 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008971 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008972 return window;
8973 }
8974
8975private:
8976 int mSpyCount{0};
8977};
8978
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008979using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008980/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008981 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8982 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008983TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8984 ScopedSilentDeath _silentDeath;
8985
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008986 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008987 spy->setTrustedOverlay(false);
8988 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8989 ".* not a trusted overlay");
8990}
8991
8992/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008993 * Input injection into a display with a spy window but no foreground windows should succeed.
8994 */
8995TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008996 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008997 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8998
8999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9000 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9002 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9003}
9004
9005/**
9006 * Verify the order in which different input windows receive events. The touched foreground window
9007 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9008 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9009 * receive events before ones belows it.
9010 *
9011 * Here, we set up a scenario with four windows in the following Z order from the top:
9012 * spy1, spy2, window, spy3.
9013 * We then inject an event and verify that the foreground "window" receives it first, followed by
9014 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9015 * window.
9016 */
9017TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9018 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009019 auto spy1 = createSpy();
9020 auto spy2 = createSpy();
9021 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009022 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9023 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9024 const size_t numChannels = channels.size();
9025
Michael Wright8e9a8562022-02-09 13:44:29 +00009026 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009027 if (!epollFd.ok()) {
9028 FAIL() << "Failed to create epoll fd";
9029 }
9030
9031 for (size_t i = 0; i < numChannels; i++) {
9032 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9033 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9034 FAIL() << "Failed to add fd to epoll";
9035 }
9036 }
9037
9038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9039 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9041
9042 std::vector<size_t> eventOrder;
9043 std::vector<struct epoll_event> events(numChannels);
9044 for (;;) {
9045 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9046 (100ms).count());
9047 if (nFds < 0) {
9048 FAIL() << "Failed to call epoll_wait";
9049 }
9050 if (nFds == 0) {
9051 break; // epoll_wait timed out
9052 }
9053 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009054 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009055 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009056 channels[i]->consumeMotionDown();
9057 }
9058 }
9059
9060 // Verify the order in which the events were received.
9061 EXPECT_EQ(3u, eventOrder.size());
9062 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9063 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9064 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9065}
9066
9067/**
9068 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9069 */
9070TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9071 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009072 auto spy = createSpy();
9073 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9075
9076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9077 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9079 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9080 spy->assertNoEvents();
9081}
9082
9083/**
9084 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9085 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9086 * to the window.
9087 */
9088TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9089 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009090 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009091 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9092 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9093
9094 // Inject an event outside the spy window's touchable region.
9095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9096 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9098 window->consumeMotionDown();
9099 spy->assertNoEvents();
9100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9101 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9102 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9103 window->consumeMotionUp();
9104 spy->assertNoEvents();
9105
9106 // Inject an event inside the spy window's touchable region.
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9108 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9109 {5, 10}))
9110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9111 window->consumeMotionDown();
9112 spy->consumeMotionDown();
9113}
9114
9115/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009116 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009117 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009118 */
9119TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9120 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009121 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009122 auto spy = createSpy();
9123 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009124 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009125 spy->setFrame(Rect{0, 0, 20, 20});
9126 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9127
9128 // Inject an event outside the spy window's frame and touchable region.
9129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009130 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9131 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009132 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9133 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009134 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009135}
9136
9137/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009138 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9139 * pointers that are down within its bounds.
9140 */
9141TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9142 auto windowLeft = createForeground();
9143 windowLeft->setFrame({0, 0, 100, 200});
9144 auto windowRight = createForeground();
9145 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009146 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009147 spy->setFrame({0, 0, 200, 200});
9148 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9149
9150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9151 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9152 {50, 50}))
9153 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9154 windowLeft->consumeMotionDown();
9155 spy->consumeMotionDown();
9156
9157 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009158 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009159 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009160 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9161 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009162 .build();
9163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9164 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9165 InputEventInjectionSync::WAIT_FOR_RESULT))
9166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9167 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009168 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009169}
9170
9171/**
9172 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9173 * the spy should receive the second pointer with ACTION_DOWN.
9174 */
9175TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9176 auto window = createForeground();
9177 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009178 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009179 spyRight->setFrame({100, 0, 200, 200});
9180 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9181
9182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9183 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9184 {50, 50}))
9185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9186 window->consumeMotionDown();
9187 spyRight->assertNoEvents();
9188
9189 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009190 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009191 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009192 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9193 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009194 .build();
9195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9196 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9197 InputEventInjectionSync::WAIT_FOR_RESULT))
9198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009199 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009200 spyRight->consumeMotionDown();
9201}
9202
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009203/**
9204 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9205 * windows should be allowed to control split touch.
9206 */
9207TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009208 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009209 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009210 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009211 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009212
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009213 auto window = createForeground();
9214 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009215
9216 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9217
9218 // First finger down, no window touched.
9219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9220 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9221 {100, 200}))
9222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9223 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9224 window->assertNoEvents();
9225
9226 // Second finger down on window, the window should receive touch down.
9227 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009228 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009229 .displayId(ADISPLAY_ID_DEFAULT)
9230 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009231 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9232 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009233 .build();
9234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9235 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9236 InputEventInjectionSync::WAIT_FOR_RESULT))
9237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9238
9239 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009240 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009241}
9242
9243/**
9244 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9245 * do not receive key events.
9246 */
9247TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009248 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009249 spy->setFocusable(false);
9250
9251 auto window = createForeground();
9252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9253 setFocusedWindow(window);
9254 window->consumeFocusEvent(true);
9255
9256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9257 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9258 window->consumeKeyDown(ADISPLAY_ID_NONE);
9259
9260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9261 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9262 window->consumeKeyUp(ADISPLAY_ID_NONE);
9263
9264 spy->assertNoEvents();
9265}
9266
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009267using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9268
9269/**
9270 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9271 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9272 */
9273TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9274 auto window = createForeground();
9275 auto spy1 = createSpy();
9276 auto spy2 = createSpy();
9277 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9278
9279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9280 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9282 window->consumeMotionDown();
9283 spy1->consumeMotionDown();
9284 spy2->consumeMotionDown();
9285
9286 // Pilfer pointers from the second spy window.
9287 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9288 spy2->assertNoEvents();
9289 spy1->consumeMotionCancel();
9290 window->consumeMotionCancel();
9291
9292 // The rest of the gesture should only be sent to the second spy window.
9293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9294 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9295 ADISPLAY_ID_DEFAULT))
9296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9297 spy2->consumeMotionMove();
9298 spy1->assertNoEvents();
9299 window->assertNoEvents();
9300}
9301
9302/**
9303 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9304 * in the middle of the gesture.
9305 */
9306TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9307 auto window = createForeground();
9308 auto spy = createSpy();
9309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9310
9311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9312 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9314 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9315 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9316
9317 window->releaseChannel();
9318
9319 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9320
9321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9322 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9324 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9325}
9326
9327/**
9328 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9329 * the spy, but not to any other windows.
9330 */
9331TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9332 auto spy = createSpy();
9333 auto window = createForeground();
9334
9335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9336
9337 // First finger down on the window and the spy.
9338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9339 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9340 {100, 200}))
9341 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9342 spy->consumeMotionDown();
9343 window->consumeMotionDown();
9344
9345 // Spy window pilfers the pointers.
9346 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9347 window->consumeMotionCancel();
9348
9349 // Second finger down on the window and spy, but the window should not receive the pointer down.
9350 const MotionEvent secondFingerDownEvent =
9351 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9352 .displayId(ADISPLAY_ID_DEFAULT)
9353 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009354 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9355 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009356 .build();
9357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9358 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9359 InputEventInjectionSync::WAIT_FOR_RESULT))
9360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9361
Harry Cutts33476232023-01-30 19:57:29 +00009362 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009363
9364 // Third finger goes down outside all windows, so injection should fail.
9365 const MotionEvent thirdFingerDownEvent =
9366 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9367 .displayId(ADISPLAY_ID_DEFAULT)
9368 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009369 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9370 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9371 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009372 .build();
9373 ASSERT_EQ(InputEventInjectionResult::FAILED,
9374 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9375 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009376 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009377
9378 spy->assertNoEvents();
9379 window->assertNoEvents();
9380}
9381
9382/**
9383 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9384 */
9385TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9386 auto spy = createSpy();
9387 spy->setFrame(Rect(0, 0, 100, 100));
9388 auto window = createForeground();
9389 window->setFrame(Rect(0, 0, 200, 200));
9390
9391 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9392
9393 // First finger down on the window only
9394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9395 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9396 {150, 150}))
9397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9398 window->consumeMotionDown();
9399
9400 // Second finger down on the spy and window
9401 const MotionEvent secondFingerDownEvent =
9402 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9403 .displayId(ADISPLAY_ID_DEFAULT)
9404 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009405 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9406 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009407 .build();
9408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9409 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9410 InputEventInjectionSync::WAIT_FOR_RESULT))
9411 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9412 spy->consumeMotionDown();
9413 window->consumeMotionPointerDown(1);
9414
9415 // Third finger down on the spy and window
9416 const MotionEvent thirdFingerDownEvent =
9417 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9418 .displayId(ADISPLAY_ID_DEFAULT)
9419 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009420 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9421 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9422 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009423 .build();
9424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9425 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9426 InputEventInjectionSync::WAIT_FOR_RESULT))
9427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9428 spy->consumeMotionPointerDown(1);
9429 window->consumeMotionPointerDown(2);
9430
9431 // Spy window pilfers the pointers.
9432 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9433 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9434 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9435
9436 spy->assertNoEvents();
9437 window->assertNoEvents();
9438}
9439
9440/**
9441 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9442 * other windows should be canceled. If this results in the cancellation of all pointers for some
9443 * window, then that window should receive ACTION_CANCEL.
9444 */
9445TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9446 auto spy = createSpy();
9447 spy->setFrame(Rect(0, 0, 100, 100));
9448 auto window = createForeground();
9449 window->setFrame(Rect(0, 0, 200, 200));
9450
9451 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9452
9453 // First finger down on both spy and window
9454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9455 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9456 {10, 10}))
9457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9458 window->consumeMotionDown();
9459 spy->consumeMotionDown();
9460
9461 // Second finger down on the spy and window
9462 const MotionEvent secondFingerDownEvent =
9463 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9464 .displayId(ADISPLAY_ID_DEFAULT)
9465 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009466 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9467 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009468 .build();
9469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9470 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9471 InputEventInjectionSync::WAIT_FOR_RESULT))
9472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9473 spy->consumeMotionPointerDown(1);
9474 window->consumeMotionPointerDown(1);
9475
9476 // Spy window pilfers the pointers.
9477 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9478 window->consumeMotionCancel();
9479
9480 spy->assertNoEvents();
9481 window->assertNoEvents();
9482}
9483
9484/**
9485 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9486 * be sent to other windows
9487 */
9488TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9489 auto spy = createSpy();
9490 spy->setFrame(Rect(0, 0, 100, 100));
9491 auto window = createForeground();
9492 window->setFrame(Rect(0, 0, 200, 200));
9493
9494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9495
9496 // First finger down on both window and spy
9497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9498 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9499 {10, 10}))
9500 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9501 window->consumeMotionDown();
9502 spy->consumeMotionDown();
9503
9504 // Spy window pilfers the pointers.
9505 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9506 window->consumeMotionCancel();
9507
9508 // Second finger down on the window only
9509 const MotionEvent secondFingerDownEvent =
9510 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9511 .displayId(ADISPLAY_ID_DEFAULT)
9512 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009513 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9514 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009515 .build();
9516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9517 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9518 InputEventInjectionSync::WAIT_FOR_RESULT))
9519 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9520 window->consumeMotionDown();
9521 window->assertNoEvents();
9522
9523 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9524 spy->consumeMotionMove();
9525 spy->assertNoEvents();
9526}
9527
Prabir Pradhand65552b2021-10-07 11:23:50 -07009528class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9529public:
9530 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9531 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9532 std::make_shared<FakeApplicationHandle>();
9533 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009534 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9535 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009536 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009537 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009538 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009539 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009540 overlay->setTrustedOverlay(true);
9541
9542 std::shared_ptr<FakeApplicationHandle> application =
9543 std::make_shared<FakeApplicationHandle>();
9544 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009545 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9546 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009547 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009548 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009549
9550 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9552 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009553 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009554 return {std::move(overlay), std::move(window)};
9555 }
9556
9557 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009558 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009559 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009560 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009561 }
9562
9563 void sendStylusEvent(int32_t action) {
9564 NotifyMotionArgs motionArgs =
9565 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9566 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009567 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009568 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009569 }
9570};
9571
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009572using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9573
9574TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9575 ScopedSilentDeath _silentDeath;
9576
Prabir Pradhand65552b2021-10-07 11:23:50 -07009577 auto [overlay, window] = setupStylusOverlayScenario();
9578 overlay->setTrustedOverlay(false);
9579 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9580 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9581 ".* not a trusted overlay");
9582}
9583
9584TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9585 auto [overlay, window] = setupStylusOverlayScenario();
9586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9587
9588 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9589 overlay->consumeMotionDown();
9590 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9591 overlay->consumeMotionUp();
9592
9593 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9594 window->consumeMotionDown();
9595 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9596 window->consumeMotionUp();
9597
9598 overlay->assertNoEvents();
9599 window->assertNoEvents();
9600}
9601
9602TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9603 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009604 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009605 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9606
9607 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9608 overlay->consumeMotionDown();
9609 window->consumeMotionDown();
9610 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9611 overlay->consumeMotionUp();
9612 window->consumeMotionUp();
9613
9614 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9615 window->consumeMotionDown();
9616 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9617 window->consumeMotionUp();
9618
9619 overlay->assertNoEvents();
9620 window->assertNoEvents();
9621}
9622
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009623/**
9624 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9625 * The scenario is as follows:
9626 * - The stylus interceptor overlay is configured as a spy window.
9627 * - The stylus interceptor spy receives the start of a new stylus gesture.
9628 * - It pilfers pointers and then configures itself to no longer be a spy.
9629 * - The stylus interceptor continues to receive the rest of the gesture.
9630 */
9631TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9632 auto [overlay, window] = setupStylusOverlayScenario();
9633 overlay->setSpy(true);
9634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9635
9636 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9637 overlay->consumeMotionDown();
9638 window->consumeMotionDown();
9639
9640 // The interceptor pilfers the pointers.
9641 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9642 window->consumeMotionCancel();
9643
9644 // The interceptor configures itself so that it is no longer a spy.
9645 overlay->setSpy(false);
9646 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9647
9648 // It continues to receive the rest of the stylus gesture.
9649 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9650 overlay->consumeMotionMove();
9651 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9652 overlay->consumeMotionUp();
9653
9654 window->assertNoEvents();
9655}
9656
Prabir Pradhan5735a322022-04-11 17:23:34 +00009657struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009658 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009659 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009660 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9661 std::unique_ptr<InputDispatcher>& mDispatcher;
9662
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009663 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009664 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9665
9666 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9667 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9668 ADISPLAY_ID_DEFAULT, {100, 200},
9669 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9670 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9671 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9672 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9673 }
9674
9675 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009676 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009677 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009678 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009679 mPolicyFlags);
9680 }
9681
9682 sp<FakeWindowHandle> createWindow() const {
9683 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9684 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009685 sp<FakeWindowHandle> window =
9686 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9687 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009688 window->setOwnerInfo(mPid, mUid);
9689 return window;
9690 }
9691};
9692
9693using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9694
9695TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009696 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009697 auto window = owner.createWindow();
9698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9699
9700 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9701 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9702 window->consumeMotionDown();
9703
9704 setFocusedWindow(window);
9705 window->consumeFocusEvent(true);
9706
9707 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9708 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9709 window->consumeKeyDown(ADISPLAY_ID_NONE);
9710}
9711
9712TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009713 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009714 auto window = owner.createWindow();
9715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9716
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009717 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009718 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9719 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9720
9721 setFocusedWindow(window);
9722 window->consumeFocusEvent(true);
9723
9724 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9725 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9726 window->assertNoEvents();
9727}
9728
9729TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009730 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009731 auto window = owner.createWindow();
9732 auto spy = owner.createWindow();
9733 spy->setSpy(true);
9734 spy->setTrustedOverlay(true);
9735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9736
9737 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9738 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9739 spy->consumeMotionDown();
9740 window->consumeMotionDown();
9741}
9742
9743TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009744 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009745 auto window = owner.createWindow();
9746
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009747 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009748 auto randosSpy = rando.createWindow();
9749 randosSpy->setSpy(true);
9750 randosSpy->setTrustedOverlay(true);
9751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9752
9753 // The event is targeted at owner's window, so injection should succeed, but the spy should
9754 // not receive the event.
9755 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9756 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9757 randosSpy->assertNoEvents();
9758 window->consumeMotionDown();
9759}
9760
9761TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009762 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009763 auto window = owner.createWindow();
9764
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009765 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009766 auto randosSpy = rando.createWindow();
9767 randosSpy->setSpy(true);
9768 randosSpy->setTrustedOverlay(true);
9769 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9770
9771 // A user that has injection permission can inject into any window.
9772 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9773 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9774 ADISPLAY_ID_DEFAULT));
9775 randosSpy->consumeMotionDown();
9776 window->consumeMotionDown();
9777
9778 setFocusedWindow(randosSpy);
9779 randosSpy->consumeFocusEvent(true);
9780
9781 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9782 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9783 window->assertNoEvents();
9784}
9785
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009786TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009787 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009788 auto window = owner.createWindow();
9789
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009790 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009791 auto randosWindow = rando.createWindow();
9792 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9793 randosWindow->setWatchOutsideTouch(true);
9794 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9795
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009796 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009797 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9798 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9799 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009800 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009801}
9802
Garfield Tane84e6f92019-08-29 17:28:41 -07009803} // namespace android::inputdispatcher