blob: 77d5391380cdcacc9ef9ed35d267b6795d131438 [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"
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070019#include "TestInputListenerMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Cody Heiner166a5af2023-07-07 12:25:00 -070021#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070022#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080023#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080024#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070025#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070026#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000027#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080028#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080029#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070031#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080032#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080033#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034
Garfield Tan1c7bc862020-01-28 13:24:04 -080035#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080036#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070037#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080038#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080039#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040
Garfield Tan1c7bc862020-01-28 13:24:04 -080041using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050042using android::gui::FocusRequest;
43using android::gui::TouchOcclusionMode;
44using android::gui::WindowInfo;
45using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080046using android::os::InputEventInjectionResult;
47using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080048
Garfield Tane84e6f92019-08-29 17:28:41 -070049namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080050
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080052using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070053
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070054namespace {
55
Michael Wrightd02c5b62014-02-10 15:10:22 -080056// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000057static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
59// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000060static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080061static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080062
Jeff Brownf086ddb2014-02-11 14:28:48 -080063// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000064static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
65static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080066
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000067// Ensure common actions are interchangeable between keys and motions for convenience.
68static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
69static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080070static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
71static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
72static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
73static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070074static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070076static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080077static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080078static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080079/**
80 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
81 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
82 * index 0) is the new pointer going down. The same pointer could have been placed at a different
83 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
84 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
85 * pointer id=0 leaves but the pointer id=1 remains.
86 */
87static constexpr int32_t POINTER_0_DOWN =
88 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080089static constexpr int32_t POINTER_1_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000091static constexpr int32_t POINTER_2_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000093static constexpr int32_t POINTER_3_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000095static constexpr int32_t POINTER_0_UP =
96 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080097static constexpr int32_t POINTER_1_UP =
98 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000099static constexpr int32_t POINTER_2_UP =
100 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800101
Antonio Kantek15beb512022-06-13 22:35:41 +0000102// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000103static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000104static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000105
Antonio Kantek15beb512022-06-13 22:35:41 +0000106// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000107static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000108static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000109
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000110// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000111static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000112
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800113static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
114
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700115/**
116 * If we expect to receive the event, the timeout can be made very long. When the test are running
117 * correctly, we will actually never wait until the end of the timeout because the wait will end
118 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
119 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
120 * developer can see the failure quickly (on human scale).
121 */
122static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
123/**
124 * When no event is expected, we can have a very short timeout. A large value here would slow down
125 * the tests. In the unlikely event of system being too slow, the event may still be present but the
126 * timeout would complete before it is consumed. This would result in test flakiness. If this
127 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
128 * would get noticed and addressed quickly.
129 */
130static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
131
Arthur Hungc539dbb2022-12-08 07:45:36 +0000132static constexpr int expectedWallpaperFlags =
133 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
134
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800135using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
136
chaviwd1c23182019-12-20 18:44:56 -0800137struct PointF {
138 float x;
139 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800140 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800141};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800142
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700143inline std::string pointFToString(const PointF& p) {
144 return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
145}
146
Gang Wang342c9272020-01-13 13:15:04 -0500147/**
148 * Return a DOWN key event with KEYCODE_A.
149 */
150static KeyEvent getTestKeyEvent() {
151 KeyEvent event;
152
Garfield Tanfbe732e2020-01-24 11:26:14 -0800153 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
154 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
155 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500156 return event;
157}
158
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800159MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700160 *result_listener << "expected downTime " << downTime << ", but got " << arg.getDownTime();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800161 return arg.getDownTime() == downTime;
162}
163
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800164MATCHER_P(WithSource, source, "InputEvent with specified source") {
165 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
166 << inputEventSourceToString(arg.getSource());
167 return arg.getSource() == source;
168}
169
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800170MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171 *result_listener << "expected flags " << std::hex << flags << ", but got " << arg.getFlags();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800172 return arg.getFlags() == flags;
173}
174
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800175MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
176 if (arg.getPointerCount() != 1) {
177 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
178 return false;
179 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700180 const float receivedX = arg.getX(/*pointerIndex=*/0);
181 const float receivedY = arg.getY(/*pointerIndex=*/0);
182 *result_listener << "expected coords (" << x << ", " << y << "), but got (" << receivedX << ", "
183 << receivedY << ")";
184 return receivedX == x && receivedY == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800185}
186
Prabir Pradhan0dfcac72023-10-05 20:04:21 +0000187MATCHER_P2(WithRawCoords, x, y, "MotionEvent with specified raw coordinates") {
188 if (arg.getPointerCount() != 1) {
189 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
190 return false;
191 }
192 const float receivedX = arg.getRawX(/*pointerIndex=*/0);
193 const float receivedY = arg.getRawY(/*pointerIndex=*/0);
194 *result_listener << "expected raw coords (" << x << ", " << y << "), but got (" << receivedX
195 << ", " << receivedY << ")";
196 return receivedX == x && receivedY == y;
197}
198
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800199MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700200 *result_listener << "expected pointerCount " << pointerCount << ", but got "
201 << arg.getPointerCount();
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800202 return arg.getPointerCount() == pointerCount;
203}
204
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800205MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
206 // Build a map for the received pointers, by pointer id
207 std::map<int32_t /*pointerId*/, PointF> actualPointers;
208 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
209 const int32_t pointerId = arg.getPointerId(pointerIndex);
210 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
211 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700212 *result_listener << "expected pointers " << dumpMap(pointers, constToString, pointFToString)
213 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800214 return pointers == actualPointers;
215}
216
Michael Wrightd02c5b62014-02-10 15:10:22 -0800217// --- FakeInputDispatcherPolicy ---
218
219class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000220 struct AnrResult {
221 sp<IBinder> token{};
222 gui::Pid pid{gui::Pid::INVALID};
223 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800224
Michael Wrightd02c5b62014-02-10 15:10:22 -0800225public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000226 FakeInputDispatcherPolicy() = default;
227 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800228
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800229 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700230 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700231 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700232 EXPECT_EQ(event.getDisplayId(), args.displayId);
233
234 const auto& keyEvent = static_cast<const KeyEvent&>(event);
235 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
236 EXPECT_EQ(keyEvent.getAction(), args.action);
237 });
Jackal Guof9696682018-10-05 12:23:23 +0800238 }
239
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700240 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
241 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700242 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700243 EXPECT_EQ(event.getDisplayId(), args.displayId);
244
245 const auto& motionEvent = static_cast<const MotionEvent&>(event);
246 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
247 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000248 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
249 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
250 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
251 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700252 });
Jackal Guof9696682018-10-05 12:23:23 +0800253 }
254
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700255 void assertFilterInputEventWasNotCalled() {
256 std::scoped_lock lock(mLock);
257 ASSERT_EQ(nullptr, mFilteredEvent);
258 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800259
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800260 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700261 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800262 ASSERT_TRUE(mConfigurationChangedTime)
263 << "Timed out waiting for configuration changed call";
264 ASSERT_EQ(*mConfigurationChangedTime, when);
265 mConfigurationChangedTime = std::nullopt;
266 }
267
268 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800270 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800271 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800272 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
273 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
274 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
275 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
276 mLastNotifySwitch = std::nullopt;
277 }
278
chaviwfd6d3512019-03-25 13:23:49 -0700279 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700280 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800281 ASSERT_EQ(touchedToken, mOnPointerDownToken);
282 mOnPointerDownToken.clear();
283 }
284
285 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700286 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800287 ASSERT_TRUE(mOnPointerDownToken == nullptr)
288 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700289 }
290
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700291 // This function must be called soon after the expected ANR timer starts,
292 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500293 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700294 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500295 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800296 std::unique_lock lock(mLock);
297 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500298 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800299 ASSERT_NO_FATAL_FAILURE(
300 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500301 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700302 }
303
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000304 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800305 const sp<WindowInfoHandle>& window) {
306 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
307 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
308 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500309 }
310
Prabir Pradhanedd96402022-02-15 01:46:16 -0800311 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
312 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000313 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800314 std::unique_lock lock(mLock);
315 android::base::ScopedLockAssertion assumeLocked(mLock);
316 AnrResult result;
317 ASSERT_NO_FATAL_FAILURE(result =
318 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000319 ASSERT_EQ(expectedToken, result.token);
320 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500321 }
322
Prabir Pradhanedd96402022-02-15 01:46:16 -0800323 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000324 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500325 std::unique_lock lock(mLock);
326 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800327 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
328 const auto& [token, _] = result;
329 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000330 }
331
Prabir Pradhanedd96402022-02-15 01:46:16 -0800332 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000333 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800334 std::unique_lock lock(mLock);
335 android::base::ScopedLockAssertion assumeLocked(mLock);
336 AnrResult result;
337 ASSERT_NO_FATAL_FAILURE(
338 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000339 ASSERT_EQ(expectedToken, result.token);
340 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800341 }
342
343 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000344 sp<IBinder> getResponsiveWindowToken() {
345 std::unique_lock lock(mLock);
346 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800347 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
348 const auto& [token, _] = result;
349 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700350 }
351
352 void assertNotifyAnrWasNotCalled() {
353 std::scoped_lock lock(mLock);
354 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800355 ASSERT_TRUE(mAnrWindows.empty());
356 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500357 << "ANR was not called, but please also consume the 'connection is responsive' "
358 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700359 }
360
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000361 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800362 std::unique_lock lock(mLock);
363 base::ScopedLockAssertion assumeLocked(mLock);
364
365 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
366 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000367 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800368 enabled;
369 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000370 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
371 << ") to be called.";
372 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800373 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 auto request = *mPointerCaptureRequest;
375 mPointerCaptureRequest.reset();
376 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
378
379 void assertSetPointerCaptureNotCalled() {
380 std::unique_lock lock(mLock);
381 base::ScopedLockAssertion assumeLocked(mLock);
382
383 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000384 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800385 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000386 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800387 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000388 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800389 }
390
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700391 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
392 const sp<IBinder>& targetToken) {
393 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800394 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800395 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800396 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800397 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800398 }
399
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800400 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
401 std::unique_lock lock(mLock);
402 base::ScopedLockAssertion assumeLocked(mLock);
403 std::optional<sp<IBinder>> receivedToken =
404 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
405 mNotifyInputChannelBroken);
406 ASSERT_TRUE(receivedToken.has_value());
407 ASSERT_EQ(token, *receivedToken);
408 }
409
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800410 /**
411 * Set policy timeout. A value of zero means next key will not be intercepted.
412 */
413 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
414 mInterceptKeyTimeout = timeout;
415 }
416
Josep del Riob3981622023-04-18 15:49:45 +0000417 void assertUserActivityPoked() {
418 std::scoped_lock lock(mLock);
419 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
420 }
421
422 void assertUserActivityNotPoked() {
423 std::scoped_lock lock(mLock);
424 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
425 }
426
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000427 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000428 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
429 }
430
431 void assertNotifyDeviceInteractionWasNotCalled() {
432 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
433 }
434
Michael Wrightd02c5b62014-02-10 15:10:22 -0800435private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700436 std::mutex mLock;
437 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
438 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
439 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
440 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800441
Prabir Pradhan99987712020-11-10 18:43:05 -0800442 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000443
444 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800445
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700446 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700447 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800448 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
449 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700450 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800451 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
452 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700453
arthurhungf452d0b2021-01-06 00:19:52 +0800454 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800455 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000456 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800457
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800458 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
459
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000460 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000461
Prabir Pradhanedd96402022-02-15 01:46:16 -0800462 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
463 // for a specific container to become non-empty. When the container is non-empty, return the
464 // first entry from the container and erase it.
465 template <class T>
466 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
467 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
468 // If there is an ANR, Dispatcher won't be idle because there are still events
469 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
470 // before checking if ANR was called.
471 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
472 // to provide it some time to act. 100ms seems reasonable.
473 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
474 const std::chrono::time_point start = std::chrono::steady_clock::now();
475 std::optional<T> token =
476 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
477 if (!token.has_value()) {
478 ADD_FAILURE() << "Did not receive the ANR callback";
479 return {};
480 }
481
482 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
483 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
484 // the dispatcher started counting before this function was called
485 if (std::chrono::abs(timeout - waited) > 100ms) {
486 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
487 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
488 << "ms, but waited "
489 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
490 << "ms instead";
491 }
492 return *token;
493 }
494
495 template <class T>
496 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
497 std::queue<T>& storage,
498 std::unique_lock<std::mutex>& lock,
499 std::condition_variable& condition)
500 REQUIRES(mLock) {
501 condition.wait_for(lock, timeout,
502 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
503 if (storage.empty()) {
504 ADD_FAILURE() << "Did not receive the expected callback";
505 return std::nullopt;
506 }
507 T item = storage.front();
508 storage.pop();
509 return std::make_optional(item);
510 }
511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700513 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800514 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800515 }
516
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000517 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800518 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700519 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800520 ASSERT_TRUE(pid.has_value());
521 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700522 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500523 }
524
Prabir Pradhanedd96402022-02-15 01:46:16 -0800525 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000526 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500527 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800528 ASSERT_TRUE(pid.has_value());
529 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500530 mNotifyAnr.notify_all();
531 }
532
533 void notifyNoFocusedWindowAnr(
534 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
535 std::scoped_lock lock(mLock);
536 mAnrApplications.push(applicationHandle);
537 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800538 }
539
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800540 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
541 std::scoped_lock lock(mLock);
542 mBrokenInputChannels.push(connectionToken);
543 mNotifyInputChannelBroken.notify_all();
544 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800545
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600546 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700547
Chris Yef59a2f42020-10-16 12:55:26 -0700548 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
549 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
550 const std::vector<float>& values) override {}
551
552 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
553 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000554
Chris Yefb552902021-02-03 17:18:37 -0800555 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
556
Prabir Pradhana41d2442023-04-20 21:30:40 +0000557 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700558 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000559 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700560 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000561 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
562 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800563 break;
564 }
565
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700566 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000567 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
568 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800569 break;
570 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700571 default: {
572 ADD_FAILURE() << "Should only filter keys or motions";
573 break;
574 }
Jackal Guof9696682018-10-05 12:23:23 +0800575 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576 return true;
577 }
578
Prabir Pradhana41d2442023-04-20 21:30:40 +0000579 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
580 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800581 // Clear intercept state when we handled the event.
582 mInterceptKeyTimeout = 0ms;
583 }
584 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600586 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587
Prabir Pradhana41d2442023-04-20 21:30:40 +0000588 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800589 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
590 // Clear intercept state so we could dispatch the event in next wake.
591 mInterceptKeyTimeout = 0ms;
592 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Prabir Pradhana41d2442023-04-20 21:30:40 +0000595 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
596 uint32_t) override {
597 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800598 }
599
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600600 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
601 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700602 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800603 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
604 * essentially a passthrough for notifySwitch.
605 */
Harry Cutts33476232023-01-30 19:57:29 +0000606 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800607 }
608
Josep del Riob3981622023-04-18 15:49:45 +0000609 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
610 std::scoped_lock lock(mLock);
611 mPokedUserActivity = true;
612 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600614 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700615 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700616 mOnPointerDownToken = newToken;
617 }
618
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000619 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800620 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000621 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800622 mPointerCaptureChangedCondition.notify_all();
623 }
624
arthurhungf452d0b2021-01-06 00:19:52 +0800625 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
626 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800627 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800628 mDropTargetWindowToken = token;
629 }
630
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000631 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000632 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000633 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
634 }
635
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700636 void assertFilterInputEventWasCalledInternal(
637 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700638 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800639 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700640 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800641 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800642 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800643};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700644} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800645
Michael Wrightd02c5b62014-02-10 15:10:22 -0800646// --- InputDispatcherTest ---
647
648class InputDispatcherTest : public testing::Test {
649protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000650 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700651 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000653 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000654 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
655 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000656 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000657 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700658 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659 }
660
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000661 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700662 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000663 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700664 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700666
667 /**
668 * Used for debugging when writing the test
669 */
670 void dumpDispatcherState() {
671 std::string dump;
672 mDispatcher->dump(dump);
673 std::stringstream ss(dump);
674 std::string to;
675
676 while (std::getline(ss, to, '\n')) {
677 ALOGE("%s", to.c_str());
678 }
679 }
Vishnu Nair958da932020-08-21 17:12:37 -0700680
Chavi Weingarten847e8512023-03-29 00:26:09 +0000681 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700682 FocusRequest request;
683 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000684 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700685 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
686 request.displayId = window->getInfo()->displayId;
687 mDispatcher->setFocusedWindow(request);
688 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800689};
690
Michael Wrightd02c5b62014-02-10 15:10:22 -0800691TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
692 KeyEvent event;
693
694 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800695 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
696 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000697 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600698 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800699 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000700 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000701 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800702 << "Should reject key events with undefined action.";
703
704 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800705 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
706 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600707 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800708 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000709 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000710 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800711 << "Should reject key events with ACTION_MULTIPLE.";
712}
713
714TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
715 MotionEvent event;
716 PointerProperties pointerProperties[MAX_POINTERS + 1];
717 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800718 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800719 pointerProperties[i].clear();
720 pointerProperties[i].id = i;
721 pointerCoords[i].clear();
722 }
723
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800724 // Some constants commonly used below
725 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
726 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
727 constexpr int32_t metaState = AMETA_NONE;
728 constexpr MotionClassification classification = MotionClassification::NONE;
729
chaviw9eaa22c2020-07-01 16:21:27 -0700730 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800731 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800732 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000733 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700734 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
736 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000737 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000739 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000740 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800741 << "Should reject motion events with undefined action.";
742
743 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800744 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800745 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
746 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
747 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
748 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with pointer down index too large.";
754
Garfield Tanfbe732e2020-01-24 11:26:14 -0800755 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700756 AMOTION_EVENT_ACTION_POINTER_DOWN |
757 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700758 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
759 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700760 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with pointer down index too small.";
766
767 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800768 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800769 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
770 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
772 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer up index too large.";
778
Garfield Tanfbe732e2020-01-24 11:26:14 -0800779 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700780 AMOTION_EVENT_ACTION_POINTER_UP |
781 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700782 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
783 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700784 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with pointer up index too small.";
790
791 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800792 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
793 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700794 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700795 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
796 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000797 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800798 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000799 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000800 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800801 << "Should reject motion events with 0 pointers.";
802
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with more than MAX_POINTERS pointers.";
813
814 // Rejects motion events with invalid pointer ids.
815 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with pointer ids less than 0.";
826
827 pointerProperties[0].id = MAX_POINTER_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,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000833 /*pointerCount=*/1, 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 pointer ids greater than MAX_POINTER_ID.";
838
839 // Rejects motion events with duplicate pointer ids.
840 pointerProperties[0].id = 1;
841 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800842 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
843 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700844 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700845 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
846 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000847 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800848 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000849 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000850 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800851 << "Should reject motion events with duplicate pointer ids.";
852}
853
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800854/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
855
856TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
857 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000858 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800859 ASSERT_TRUE(mDispatcher->waitForIdle());
860
861 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
862}
863
864TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000865 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
866 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000867 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800868
869 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
870 args.policyFlags |= POLICY_FLAG_TRUSTED;
871 mFakePolicy->assertNotifySwitchWasCalled(args);
872}
873
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700874namespace {
875
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700876static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700877// Default input dispatching timeout if there is no focused application or paused window
878// from which to determine an appropriate dispatching timeout.
879static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
880 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
881 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800882
883class FakeApplicationHandle : public InputApplicationHandle {
884public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 FakeApplicationHandle() {
886 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700887 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500888 mInfo.dispatchingTimeoutMillis =
889 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700890 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800891 virtual ~FakeApplicationHandle() {}
892
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000893 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700894
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500895 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
896 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800898};
899
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800900class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800901public:
Garfield Tan15601662020-09-22 15:32:38 -0700902 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800903 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700904 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800905 }
906
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700907 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700908 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700909 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 if (!consumeSeq) {
911 return nullptr;
912 }
913 finishEvent(*consumeSeq);
914 return event;
915 }
916
917 /**
918 * Receive an event without acknowledging it.
919 * Return the sequence number that could later be used to send finished signal.
920 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700921 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
922 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800923 uint32_t consumeSeq;
924 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800925
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800926 std::chrono::time_point start = std::chrono::steady_clock::now();
927 status_t status = WOULD_BLOCK;
928 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000929 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930 &event);
931 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700932 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 break;
934 }
935 }
936
937 if (status == WOULD_BLOCK) {
938 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700939 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800940 }
941
942 if (status != OK) {
943 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800945 }
946 if (event == nullptr) {
947 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700948 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800949 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700950 if (outEvent != nullptr) {
951 *outEvent = event;
952 }
953 return consumeSeq;
954 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800955
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700956 /**
957 * To be used together with "receiveEvent" to complete the consumption of an event.
958 */
959 void finishEvent(uint32_t consumeSeq) {
960 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
961 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800962 }
963
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000964 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
965 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
966 ASSERT_EQ(OK, status);
967 }
968
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700969 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000970 std::optional<int32_t> expectedDisplayId,
971 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700972 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800973
974 ASSERT_NE(nullptr, event) << mName.c_str()
975 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800976 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
978 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800979
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000980 if (expectedDisplayId.has_value()) {
981 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
982 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800983
Tiger Huang8664f8c2018-10-11 19:14:35 +0800984 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700985 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800986 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700987 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000988 if (expectedFlags.has_value()) {
989 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
990 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800991 break;
992 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700993 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800994 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700995 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000996 if (expectedFlags.has_value()) {
997 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
998 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800999 break;
1000 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001001 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001002 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1003 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001004 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001005 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1006 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001007 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001008 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1009 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001010 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001011 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1012 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001013 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001014 }
1015
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001016 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001017 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001018
1019 if (event == nullptr) {
1020 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1021 return nullptr;
1022 }
1023
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001024 if (event->getType() != InputEventType::MOTION) {
1025 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001026 return nullptr;
1027 }
1028 return static_cast<MotionEvent*>(event);
1029 }
1030
1031 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1032 MotionEvent* motionEvent = consumeMotion();
1033 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1034 ASSERT_THAT(*motionEvent, matcher);
1035 }
1036
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001037 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001038 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001039 ASSERT_NE(nullptr, event) << mName.c_str()
1040 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001041 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1042 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001043
1044 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046
1047 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1048 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001049 }
1050
Prabir Pradhan99987712020-11-10 18:43:05 -08001051 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001052 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001053 ASSERT_NE(nullptr, event) << mName.c_str()
1054 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1056 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001057
1058 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1059 << mName.c_str() << ": event displayId should always be NONE.";
1060
1061 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1062 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1063 }
1064
arthurhungb89ccb02020-12-30 16:19:01 +08001065 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001066 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001067 ASSERT_NE(nullptr, event) << mName.c_str()
1068 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001070
1071 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1072 << mName.c_str() << ": event displayId should always be NONE.";
1073
1074 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1075 EXPECT_EQ(isExiting, dragEvent.isExiting());
1076 EXPECT_EQ(x, dragEvent.getX());
1077 EXPECT_EQ(y, dragEvent.getY());
1078 }
1079
Antonio Kantekf16f2832021-09-28 04:39:20 +00001080 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001081 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001082 ASSERT_NE(nullptr, event) << mName.c_str()
1083 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001084 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1085 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001086
1087 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1088 << mName.c_str() << ": event displayId should always be NONE.";
1089 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1090 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1091 }
1092
chaviwd1c23182019-12-20 18:44:56 -08001093 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001094 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 if (event == nullptr) {
1096 return;
1097 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001098 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001099 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1100 ADD_FAILURE() << "Received key event "
1101 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001102 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001103 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1104 ADD_FAILURE() << "Received motion event "
1105 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001106 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001107 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1108 ADD_FAILURE() << "Received focus event, hasFocus = "
1109 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001110 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001111 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1112 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1113 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001114 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001115 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1116 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1117 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001118 }
1119 FAIL() << mName.c_str()
1120 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001121 }
1122
1123 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1124
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001125 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1126
chaviwd1c23182019-12-20 18:44:56 -08001127protected:
1128 std::unique_ptr<InputConsumer> mConsumer;
1129 PreallocatedInputEventFactory mEventFactory;
1130
1131 std::string mName;
1132};
1133
chaviw3277faf2021-05-19 16:45:23 -05001134class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001135public:
1136 static const int32_t WIDTH = 600;
1137 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001138
Chris Yea209fde2020-07-22 13:54:51 -07001139 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001140 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001141 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001142 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001143 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001144 base::Result<std::unique_ptr<InputChannel>> channel =
1145 dispatcher->createInputChannel(name);
1146 token = (*channel)->getConnectionToken();
1147 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001148 }
1149
1150 inputApplicationHandle->updateInfo();
1151 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1152
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001153 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001154 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001155 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001156 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001157 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001158 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001159 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001160 mInfo.globalScaleFactor = 1.0;
1161 mInfo.touchableRegion.clear();
1162 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001163 mInfo.ownerPid = WINDOW_PID;
1164 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001165 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001166 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001167 }
1168
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001169 sp<FakeWindowHandle> clone(int32_t displayId) {
1170 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1171 handle->mInfo = mInfo;
1172 handle->mInfo.displayId = displayId;
1173 handle->mInfo.id = sId++;
1174 handle->mInputReceiver = mInputReceiver;
1175 return handle;
1176 }
1177
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001178 void setTouchable(bool touchable) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1180 }
chaviwd1c23182019-12-20 18:44:56 -08001181
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001182 void setFocusable(bool focusable) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1184 }
1185
1186 void setVisible(bool visible) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1188 }
Vishnu Nair958da932020-08-21 17:12:37 -07001189
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001190 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001191 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001192 }
1193
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001194 void setPaused(bool paused) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1196 }
1197
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001198 void setPreventSplitting(bool preventSplitting) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001200 }
1201
1202 void setSlippery(bool slippery) {
1203 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1204 }
1205
1206 void setWatchOutsideTouch(bool watchOutside) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1208 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001209
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001210 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1211
1212 void setInterceptsStylus(bool interceptsStylus) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1214 }
1215
1216 void setDropInput(bool dropInput) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1218 }
1219
1220 void setDropInputIfObscured(bool dropInputIfObscured) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1222 }
1223
1224 void setNoInputChannel(bool noInputChannel) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1226 }
1227
Josep del Riob3981622023-04-18 15:49:45 +00001228 void setDisableUserActivity(bool disableUserActivity) {
1229 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1230 }
1231
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001232 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1233
chaviw3277faf2021-05-19 16:45:23 -05001234 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001235
Bernardo Rufino7393d172021-02-26 13:56:11 +00001236 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1237
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001238 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001239 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001240 mInfo.touchableRegion.clear();
1241 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001242
1243 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1244 ui::Transform translate;
1245 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1246 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001247 }
1248
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001249 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1250
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001251 void setIsWallpaper(bool isWallpaper) {
1252 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1253 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001254
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001255 void setDupTouchToWallpaper(bool hasWallpaper) {
1256 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1257 }
chaviwd1c23182019-12-20 18:44:56 -08001258
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001259 void setTrustedOverlay(bool trustedOverlay) {
1260 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1261 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001262
chaviw9eaa22c2020-07-01 16:21:27 -07001263 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1264 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1265 }
1266
1267 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001268
yunho.shinf4a80b82020-11-16 21:13:57 +09001269 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1270
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001271 KeyEvent* consumeKey() {
1272 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1273 if (event == nullptr) {
1274 ADD_FAILURE() << "Consume failed : no event";
1275 return nullptr;
1276 }
1277 if (event->getType() != InputEventType::KEY) {
1278 ADD_FAILURE() << "Instead of key event, got " << *event;
1279 return nullptr;
1280 }
1281 return static_cast<KeyEvent*>(event);
1282 }
1283
1284 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1285 KeyEvent* keyEvent = consumeKey();
1286 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1287 ASSERT_THAT(*keyEvent, matcher);
1288 }
1289
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001290 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001291 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001292 }
1293
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001294 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001295 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001296 }
1297
Svet Ganov5d3bc372020-01-26 23:11:07 -08001298 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001299 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001300 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1301 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001302 }
1303
1304 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001305 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001306 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1307 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001308 }
1309
1310 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001311 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001312 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1313 }
1314
1315 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1316 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001317 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001318 expectedFlags);
1319 }
1320
Svet Ganov5d3bc372020-01-26 23:11:07 -08001321 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001322 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1323 int32_t expectedFlags = 0) {
1324 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1325 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001327 }
1328
1329 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001330 int32_t expectedFlags = 0) {
1331 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1332 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001333 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001334 }
1335
1336 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001337 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001338 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001339 expectedFlags);
1340 }
1341
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001342 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1343 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001344 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001345 expectedFlags);
1346 }
1347
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001348 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1349 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001350 MotionEvent* motionEvent = consumeMotion();
1351 ASSERT_NE(nullptr, motionEvent);
1352 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1353 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1354 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001355 }
1356
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001357 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1358 ASSERT_NE(mInputReceiver, nullptr)
1359 << "Cannot consume events from a window with no receiver";
1360 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1361 }
1362
Prabir Pradhan99987712020-11-10 18:43:05 -08001363 void consumeCaptureEvent(bool hasCapture) {
1364 ASSERT_NE(mInputReceiver, nullptr)
1365 << "Cannot consume events from a window with no receiver";
1366 mInputReceiver->consumeCaptureEvent(hasCapture);
1367 }
1368
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001369 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1370 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001371 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001372 ASSERT_THAT(*motionEvent, matcher);
1373 }
1374
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001375 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001376 std::optional<int32_t> expectedDisplayId,
1377 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001378 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1379 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1380 expectedFlags);
1381 }
1382
arthurhungb89ccb02020-12-30 16:19:01 +08001383 void consumeDragEvent(bool isExiting, float x, float y) {
1384 mInputReceiver->consumeDragEvent(isExiting, x, y);
1385 }
1386
Antonio Kantekf16f2832021-09-28 04:39:20 +00001387 void consumeTouchModeEvent(bool inTouchMode) {
1388 ASSERT_NE(mInputReceiver, nullptr)
1389 << "Cannot consume events from a window with no receiver";
1390 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1391 }
1392
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001393 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001394 if (mInputReceiver == nullptr) {
1395 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1396 return std::nullopt;
1397 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001398 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001399 }
1400
1401 void finishEvent(uint32_t sequenceNum) {
1402 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1403 mInputReceiver->finishEvent(sequenceNum);
1404 }
1405
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001406 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1407 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1408 mInputReceiver->sendTimeline(inputEventId, timeline);
1409 }
1410
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001411 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001412 if (mInputReceiver == nullptr) {
1413 return nullptr;
1414 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001415 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001416 }
1417
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001418 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001419 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001420 if (event == nullptr) {
1421 ADD_FAILURE() << "Consume failed : no event";
1422 return nullptr;
1423 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001424 if (event->getType() != InputEventType::MOTION) {
1425 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001426 return nullptr;
1427 }
1428 return static_cast<MotionEvent*>(event);
1429 }
1430
Arthur Hungb92218b2018-08-14 12:00:21 +08001431 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001432 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001433 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001434 return; // Can't receive events if the window does not have input channel
1435 }
1436 ASSERT_NE(nullptr, mInputReceiver)
1437 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001438 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001439 }
1440
chaviwaf87b3e2019-10-01 16:59:28 -07001441 sp<IBinder> getToken() { return mInfo.token; }
1442
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001443 const std::string& getName() { return mName; }
1444
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001445 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001446 mInfo.ownerPid = ownerPid;
1447 mInfo.ownerUid = ownerUid;
1448 }
1449
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001450 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001451
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001452 void destroyReceiver() { mInputReceiver = nullptr; }
1453
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001454 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1455
chaviwd1c23182019-12-20 18:44:56 -08001456private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001457 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001458 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001459 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001460 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001461 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001462};
1463
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001464std::atomic<int32_t> FakeWindowHandle::sId{1};
1465
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001466class FakeMonitorReceiver {
1467public:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001468 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001469 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001470 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001471 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1472 }
1473
1474 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1475
1476 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1477 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1478 expectedFlags);
1479 }
1480
1481 std::optional<int32_t> receiveEvent() {
1482 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1483 }
1484
1485 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1486
1487 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1488 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1489 expectedDisplayId, expectedFlags);
1490 }
1491
1492 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1493 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1494 expectedDisplayId, expectedFlags);
1495 }
1496
1497 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1498 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1499 expectedDisplayId, expectedFlags);
1500 }
1501
1502 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1503 mInputReceiver->consumeMotionEvent(
1504 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1505 WithDisplayId(expectedDisplayId),
1506 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1507 }
1508
1509 void consumeMotionPointerDown(int32_t pointerIdx) {
1510 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1511 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1512 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1513 /*expectedFlags=*/0);
1514 }
1515
1516 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1517 mInputReceiver->consumeMotionEvent(matcher);
1518 }
1519
1520 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1521
1522 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1523
1524private:
1525 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1526};
1527
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001528static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001529 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001530 int32_t displayId = ADISPLAY_ID_NONE,
1531 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001532 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001533 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001534 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001535 KeyEvent event;
1536 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1537
1538 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001539 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001540 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1541 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001542
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001543 if (!allowKeyRepeat) {
1544 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1545 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001546 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001547 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001548}
1549
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001550static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1551 InputEventInjectionResult result =
1552 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1553 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1554 if (result != InputEventInjectionResult::TIMED_OUT) {
1555 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1556 }
1557}
1558
1559static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001560 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001561 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001562}
1563
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001564// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1565// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1566// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001567static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1568 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001569 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001570 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001571 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001572}
1573
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001574static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001575 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001576 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001577}
1578
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001579static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001580 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001581 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001582 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001583 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001584 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1585 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001586}
1587
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001588static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001589 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1590 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001591 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001592 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1593 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001594 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001595 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001596 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001597 MotionEventBuilder motionBuilder =
1598 MotionEventBuilder(action, source)
1599 .displayId(displayId)
1600 .eventTime(eventTime)
1601 .rawXCursorPosition(cursorPosition.x)
1602 .rawYCursorPosition(cursorPosition.y)
1603 .pointer(
1604 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1605 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1606 motionBuilder.downTime(eventTime);
1607 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001608
1609 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001610 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1611 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001612}
1613
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1615 int32_t displayId,
1616 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001617 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001618}
1619
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001620static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1621 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001622 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001623 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001624}
1625
Jackal Guof9696682018-10-05 12:23:23 +08001626static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1627 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1628 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001629 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001630 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1631 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001632
1633 return args;
1634}
1635
Josep del Riob3981622023-04-18 15:49:45 +00001636static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1637 int32_t displayId = ADISPLAY_ID_NONE) {
1638 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1639 // Define a valid key event.
1640 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001641 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001642 currentTime);
1643
1644 return args;
1645}
1646
1647static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1648 int32_t displayId = ADISPLAY_ID_NONE) {
1649 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1650 // Define a valid key event.
1651 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001652 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001653 AMETA_NONE, currentTime);
1654
1655 return args;
1656}
1657
Prabir Pradhan678438e2023-04-13 19:32:51 +00001658[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1659 int32_t displayId,
1660 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001661 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001662 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1663 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1664 }
1665
chaviwd1c23182019-12-20 18:44:56 -08001666 PointerProperties pointerProperties[pointerCount];
1667 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001668
chaviwd1c23182019-12-20 18:44:56 -08001669 for (size_t i = 0; i < pointerCount; i++) {
1670 pointerProperties[i].clear();
1671 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001672 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001673
chaviwd1c23182019-12-20 18:44:56 -08001674 pointerCoords[i].clear();
1675 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1676 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1677 }
Jackal Guof9696682018-10-05 12:23:23 +08001678
1679 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1680 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001681 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001682 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1683 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001684 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001685 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001686 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001687 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001688
1689 return args;
1690}
1691
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001692static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1693 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1694}
1695
chaviwd1c23182019-12-20 18:44:56 -08001696static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1697 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1698}
1699
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001700static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1701 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001702 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001703}
1704
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001705} // namespace
1706
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001707/**
1708 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1709 * broken channel.
1710 */
1711TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1713 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001714 sp<FakeWindowHandle>::make(application, mDispatcher,
1715 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001718
1719 // Window closes its channel, but the window remains.
1720 window->destroyReceiver();
1721 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1722}
1723
Arthur Hungb92218b2018-08-14 12:00:21 +08001724TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001725 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001726 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1727 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001728
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001733
1734 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001735 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001736}
1737
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001738TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001740 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1741 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001742
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001743 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001744 // Inject a MotionEvent to an unknown display.
1745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1748
1749 // Window should receive motion event.
1750 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1751}
1752
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001753/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001754 * Calling onWindowInfosChanged once should not cause any issues.
1755 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001756 * called twice.
1757 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001758TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001760 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1761 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001762 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001763
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001764 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001767 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001769
1770 // Window should receive motion event.
1771 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1772}
1773
1774/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001775 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001776 */
1777TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001779 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1780 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001781 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001782
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001783 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1784 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001786 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001787 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001789
1790 // Window should receive motion event.
1791 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1792}
1793
Arthur Hungb92218b2018-08-14 12:00:21 +08001794// The foreground window should receive the first touch down event.
1795TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001797 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001798 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001799 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001800 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001801
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001802 mDispatcher->onWindowInfosChanged(
1803 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001805 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001807
1808 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001809 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001810 windowSecond->assertNoEvents();
1811}
1812
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001813/**
1814 * Two windows: A top window, and a wallpaper behind the window.
1815 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1816 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001817 * 1. foregroundWindow <-- dup touch to wallpaper
1818 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001819 */
1820TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1822 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001823 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001824 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001825 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001826 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001827 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001828
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001829 mDispatcher->onWindowInfosChanged(
1830 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001832 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001833 {100, 200}))
1834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1835
1836 // Both foreground window and its wallpaper should receive the touch down
1837 foregroundWindow->consumeMotionDown();
1838 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1839
1840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001841 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001842 ADISPLAY_ID_DEFAULT, {110, 200}))
1843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1844
1845 foregroundWindow->consumeMotionMove();
1846 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1847
1848 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001849 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001850 foregroundWindow->consumeMotionCancel();
1851 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1852 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1853}
1854
1855/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001856 * Two fingers down on the window, and lift off the first finger.
1857 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1858 * contains a single pointer.
1859 */
1860TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1862 sp<FakeWindowHandle> window =
1863 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001865 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001866 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1868 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1869 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001870 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001871 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1872 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1873 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1874 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001875 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1877 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1878 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1879 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001880 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1881 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1882 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1883
1884 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001885 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001886 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1887 window->consumeMotionEvent(
1888 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1889}
1890
1891/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001892 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1893 * with the following differences:
1894 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1895 * clean up the connection.
1896 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1897 * Ensure that there's no crash in the dispatcher.
1898 */
1899TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1901 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001902 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001903 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001904 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001905 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001906 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001907
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001908 mDispatcher->onWindowInfosChanged(
1909 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001911 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001912 {100, 200}))
1913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1914
1915 // Both foreground window and its wallpaper should receive the touch down
1916 foregroundWindow->consumeMotionDown();
1917 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1918
1919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001920 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001921 ADISPLAY_ID_DEFAULT, {110, 200}))
1922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1923
1924 foregroundWindow->consumeMotionMove();
1925 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1926
1927 // Wallpaper closes its channel, but the window remains.
1928 wallpaperWindow->destroyReceiver();
1929 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1930
1931 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1932 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001933 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001934 foregroundWindow->consumeMotionCancel();
1935}
1936
Arthur Hungc539dbb2022-12-08 07:45:36 +00001937class ShouldSplitTouchFixture : public InputDispatcherTest,
1938 public ::testing::WithParamInterface<bool> {};
1939INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1940 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001941/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001942 * A single window that receives touch (on top), and a wallpaper window underneath it.
1943 * The top window gets a multitouch gesture.
1944 * Ensure that wallpaper gets the same gesture.
1945 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001946TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001948 sp<FakeWindowHandle> foregroundWindow =
1949 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1950 foregroundWindow->setDupTouchToWallpaper(true);
1951 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952
1953 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001954 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001955 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001957 mDispatcher->onWindowInfosChanged(
1958 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001959
1960 // Touch down on top window
1961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001962 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963 {100, 100}))
1964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1965
1966 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001967 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1969
1970 // Second finger down on the top window
1971 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001972 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001973 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001974 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1975 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976 .build();
1977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001978 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979 InputEventInjectionSync::WAIT_FOR_RESULT))
1980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1981
Harry Cutts33476232023-01-30 19:57:29 +00001982 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1983 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001985
1986 const MotionEvent secondFingerUpEvent =
1987 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1988 .displayId(ADISPLAY_ID_DEFAULT)
1989 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001990 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1991 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001992 .build();
1993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001994 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001995 InputEventInjectionSync::WAIT_FOR_RESULT))
1996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1997 foregroundWindow->consumeMotionPointerUp(0);
1998 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1999
2000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002001 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002002 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2003 AINPUT_SOURCE_TOUCHSCREEN)
2004 .displayId(ADISPLAY_ID_DEFAULT)
2005 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002006 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002007 .x(100)
2008 .y(100))
2009 .build(),
2010 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2012 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2013 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014}
2015
2016/**
2017 * Two windows: a window on the left and window on the right.
2018 * A third window, wallpaper, is behind both windows, and spans both top windows.
2019 * The first touch down goes to the left window. A second pointer touches down on the right window.
2020 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2021 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2022 * ACTION_POINTER_DOWN(1).
2023 */
2024TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2026 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002027 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002028 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002029 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030
2031 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002032 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002034 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035
2036 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002037 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002039 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002041 mDispatcher->onWindowInfosChanged(
2042 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2043 {},
2044 0,
2045 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046
2047 // Touch down on left window
2048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002049 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002050 {100, 100}))
2051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2052
2053 // Both foreground window and its wallpaper should receive the touch down
2054 leftWindow->consumeMotionDown();
2055 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2056
2057 // Second finger down on the right window
2058 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002059 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002060 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002061 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2062 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002063 .build();
2064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002065 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002066 InputEventInjectionSync::WAIT_FOR_RESULT))
2067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2068
2069 leftWindow->consumeMotionMove();
2070 // Since the touch is split, right window gets ACTION_DOWN
2071 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002072 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002073 expectedWallpaperFlags);
2074
2075 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002076 mDispatcher->onWindowInfosChanged(
2077 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078 leftWindow->consumeMotionCancel();
2079 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2080 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2081
2082 // The pointer that's still down on the right window moves, and goes to the right window only.
2083 // As far as the dispatcher's concerned though, both pointers are still present.
2084 const MotionEvent secondFingerMoveEvent =
2085 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2086 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002087 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2088 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002089 .build();
2090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002091 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002092 InputEventInjectionSync::WAIT_FOR_RESULT));
2093 rightWindow->consumeMotionMove();
2094
2095 leftWindow->assertNoEvents();
2096 rightWindow->assertNoEvents();
2097 wallpaperWindow->assertNoEvents();
2098}
2099
Arthur Hungc539dbb2022-12-08 07:45:36 +00002100/**
2101 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2102 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2103 * The right window should receive ACTION_DOWN.
2104 */
2105TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002107 sp<FakeWindowHandle> leftWindow =
2108 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2109 leftWindow->setFrame(Rect(0, 0, 200, 200));
2110 leftWindow->setDupTouchToWallpaper(true);
2111 leftWindow->setSlippery(true);
2112
2113 sp<FakeWindowHandle> rightWindow =
2114 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2115 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002116
2117 sp<FakeWindowHandle> wallpaperWindow =
2118 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2119 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002120
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002121 mDispatcher->onWindowInfosChanged(
2122 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2123 {},
2124 0,
2125 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002126
Arthur Hungc539dbb2022-12-08 07:45:36 +00002127 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002129 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002130 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002132
2133 // Both foreground window and its wallpaper should receive the touch down
2134 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002135 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2136
Arthur Hungc539dbb2022-12-08 07:45:36 +00002137 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002139 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002140 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002141 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2142
Arthur Hungc539dbb2022-12-08 07:45:36 +00002143 leftWindow->consumeMotionCancel();
2144 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2145 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002146}
2147
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002148/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002149 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2150 * interactive, it might stop sending this flag.
2151 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2152 * to have a consistent input stream.
2153 *
2154 * Test procedure:
2155 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2156 * DOWN (new gesture).
2157 *
2158 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2159 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2160 *
2161 * We technically just need a single window here, but we are using two windows (spy on top and a
2162 * regular window below) to emulate the actual situation where it happens on the device.
2163 */
2164TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2166 sp<FakeWindowHandle> spyWindow =
2167 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2168 spyWindow->setFrame(Rect(0, 0, 200, 200));
2169 spyWindow->setTrustedOverlay(true);
2170 spyWindow->setSpy(true);
2171
2172 sp<FakeWindowHandle> window =
2173 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2174 window->setFrame(Rect(0, 0, 200, 200));
2175
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002176 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002177 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002178
2179 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002180 mDispatcher->notifyMotion(
2181 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2182 .deviceId(touchDeviceId)
2183 .policyFlags(DEFAULT_POLICY_FLAGS)
2184 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2185 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002186
Prabir Pradhan678438e2023-04-13 19:32:51 +00002187 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2188 .deviceId(touchDeviceId)
2189 .policyFlags(DEFAULT_POLICY_FLAGS)
2190 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2191 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2192 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002193 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2194 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2195 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2196 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2197
2198 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002199 mDispatcher->notifyMotion(
2200 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2201 .deviceId(touchDeviceId)
2202 .policyFlags(0)
2203 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2204 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2205 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002206 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2207 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2208
2209 // We don't need to reset the device to reproduce the issue, but the reset event typically
2210 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002211 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002212
2213 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002214 mDispatcher->notifyMotion(
2215 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2216 .deviceId(touchDeviceId)
2217 .policyFlags(DEFAULT_POLICY_FLAGS)
2218 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2219 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002220 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2221 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2222
2223 // No more events
2224 spyWindow->assertNoEvents();
2225 window->assertNoEvents();
2226}
2227
2228/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002229 * Two windows: a window on the left and a window on the right.
2230 * Mouse is hovered from the right window into the left window.
2231 * Next, we tap on the left window, where the cursor was last seen.
2232 * The second tap is done onto the right window.
2233 * The mouse and tap are from two different devices.
2234 * We technically don't need to set the downtime / eventtime for these events, but setting these
2235 * explicitly helps during debugging.
2236 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2237 * In the buggy implementation, a tap on the right window would cause a crash.
2238 */
2239TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2240 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2241 sp<FakeWindowHandle> leftWindow =
2242 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2243 leftWindow->setFrame(Rect(0, 0, 200, 200));
2244
2245 sp<FakeWindowHandle> rightWindow =
2246 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2247 rightWindow->setFrame(Rect(200, 0, 400, 200));
2248
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002249 mDispatcher->onWindowInfosChanged(
2250 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002251 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2252 // stale.
2253 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2254 const int32_t mouseDeviceId = 6;
2255 const int32_t touchDeviceId = 4;
2256 // Move the cursor from right
2257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002258 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002259 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2260 AINPUT_SOURCE_MOUSE)
2261 .deviceId(mouseDeviceId)
2262 .downTime(baseTime + 10)
2263 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002264 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002265 .build()));
2266 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2267
2268 // .. to the left window
2269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2272 AINPUT_SOURCE_MOUSE)
2273 .deviceId(mouseDeviceId)
2274 .downTime(baseTime + 10)
2275 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 .build()));
2278 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2279 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2280 // Now tap the left window
2281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002283 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2284 AINPUT_SOURCE_TOUCHSCREEN)
2285 .deviceId(touchDeviceId)
2286 .downTime(baseTime + 40)
2287 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 .build()));
2290 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2291 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2292
2293 // release tap
2294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002295 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002296 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2297 AINPUT_SOURCE_TOUCHSCREEN)
2298 .deviceId(touchDeviceId)
2299 .downTime(baseTime + 40)
2300 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002301 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002302 .build()));
2303 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2304
2305 // Tap the window on the right
2306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002307 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2309 AINPUT_SOURCE_TOUCHSCREEN)
2310 .deviceId(touchDeviceId)
2311 .downTime(baseTime + 60)
2312 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 .build()));
2315 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2316
2317 // release tap
2318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002319 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002320 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2321 AINPUT_SOURCE_TOUCHSCREEN)
2322 .deviceId(touchDeviceId)
2323 .downTime(baseTime + 60)
2324 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002325 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002326 .build()));
2327 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2328
2329 // No more events
2330 leftWindow->assertNoEvents();
2331 rightWindow->assertNoEvents();
2332}
2333
2334/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002335 * Start hovering in a window. While this hover is still active, make another window appear on top.
2336 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2337 * While the top window is present, the hovering is stopped.
2338 * Later, hovering gets resumed again.
2339 * Ensure that new hover gesture is handled correctly.
2340 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2341 * to the window that's currently being hovered over.
2342 */
2343TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2344 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2345 sp<FakeWindowHandle> window =
2346 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2347 window->setFrame(Rect(0, 0, 200, 200));
2348
2349 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002350 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002351
2352 // Start hovering in the window
2353 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2354 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2355 .build());
2356 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2357
2358 // Now, an obscuring window appears!
2359 sp<FakeWindowHandle> obscuringWindow =
2360 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2361 ADISPLAY_ID_DEFAULT,
2362 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2363 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2364 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2365 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2366 obscuringWindow->setNoInputChannel(true);
2367 obscuringWindow->setFocusable(false);
2368 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002369 mDispatcher->onWindowInfosChanged(
2370 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002371
2372 // While this new obscuring window is present, the hovering is stopped
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2374 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2375 .build());
2376 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2377
2378 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002380
2381 // And a new hover gesture starts.
2382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2384 .build());
2385 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2386}
2387
2388/**
2389 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2390 * the obscuring window.
2391 */
2392TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2394 sp<FakeWindowHandle> window =
2395 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2396 window->setFrame(Rect(0, 0, 200, 200));
2397
2398 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002399 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002400
2401 // Start hovering in the window
2402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2403 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2404 .build());
2405 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2406
2407 // Now, an obscuring window appears!
2408 sp<FakeWindowHandle> obscuringWindow =
2409 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2410 ADISPLAY_ID_DEFAULT,
2411 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2412 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2413 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2414 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2415 obscuringWindow->setNoInputChannel(true);
2416 obscuringWindow->setFocusable(false);
2417 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002418 mDispatcher->onWindowInfosChanged(
2419 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002420
2421 // While this new obscuring window is present, the hovering continues. The event can't go to the
2422 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2424 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2425 .build());
2426 obscuringWindow->assertNoEvents();
2427 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2428
2429 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002430 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002431
2432 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2433 // so it should generate a HOVER_ENTER
2434 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2435 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2436 .build());
2437 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2438
2439 // Now the MOVE should be getting dispatched normally
2440 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2441 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2442 .build());
2443 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2444}
2445
2446/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002447 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2448 * events are delivered to the window.
2449 */
2450TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2452 sp<FakeWindowHandle> window =
2453 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2454 window->setFrame(Rect(0, 0, 200, 200));
2455 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2456
2457 // Start hovering in the window
2458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2459 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2460 .build());
2461 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2462
2463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2464 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2465 .build());
2466 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2467
2468 // Scroll with the mouse
2469 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2470 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2471 .build());
2472 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2473}
2474
2475using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2476
2477/**
2478 * One window. Stylus down on the window. Next, touch from another device goes down.
2479 */
2480TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2481 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2482 sp<FakeWindowHandle> window =
2483 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2484 window->setFrame(Rect(0, 0, 200, 200));
2485
2486 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2487
2488 constexpr int32_t touchDeviceId = 4;
2489 constexpr int32_t stylusDeviceId = 2;
2490
2491 // Stylus down
2492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2493 .deviceId(stylusDeviceId)
2494 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2495 .build());
2496 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2497
2498 // Touch down
2499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2500 .deviceId(touchDeviceId)
2501 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2502 .build());
2503 // Touch cancels stylus
2504 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2505 WithCoords(100, 110)));
2506 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2507 WithCoords(140, 145)));
2508
2509 // Touch move
2510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2511 .deviceId(touchDeviceId)
2512 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2513 .build());
2514 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2515 WithCoords(141, 146)));
2516
2517 // Subsequent stylus movements are dropped
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2519 .deviceId(stylusDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2521 .build());
2522 window->assertNoEvents();
2523}
2524
2525/**
2526 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2527 * down.
2528 * Similar test as above, but with added SPY window.
2529 */
2530TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2532 sp<FakeWindowHandle> window =
2533 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2534 sp<FakeWindowHandle> spyWindow =
2535 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2536 spyWindow->setFrame(Rect(0, 0, 200, 200));
2537 spyWindow->setTrustedOverlay(true);
2538 spyWindow->setSpy(true);
2539 window->setFrame(Rect(0, 0, 200, 200));
2540
2541 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2542
2543 constexpr int32_t touchDeviceId = 4;
2544 constexpr int32_t stylusDeviceId = 2;
2545
2546 // Stylus down
2547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2548 .deviceId(stylusDeviceId)
2549 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2550 .build());
2551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2552 spyWindow->consumeMotionEvent(
2553 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2554
2555 // Touch down
2556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2557 .deviceId(touchDeviceId)
2558 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2559 .build());
2560
2561 // Touch move
2562 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2563 .deviceId(touchDeviceId)
2564 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2565 .build());
2566 window->consumeMotionEvent(
2567 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2568 spyWindow->consumeMotionEvent(
2569 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2570 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2571 spyWindow->consumeMotionEvent(
2572 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2573 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2574 spyWindow->consumeMotionEvent(
2575 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2576 // Subsequent stylus movements are dropped
2577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2578 .deviceId(stylusDeviceId)
2579 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2580 .build());
2581
2582 window->assertNoEvents();
2583 spyWindow->assertNoEvents();
2584}
2585
2586/**
2587 * One window. Stylus hover on the window. Next, touch from another device goes down.
2588 */
2589TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2591 sp<FakeWindowHandle> window =
2592 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2593 window->setFrame(Rect(0, 0, 200, 200));
2594
2595 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2596
2597 constexpr int32_t touchDeviceId = 4;
2598 constexpr int32_t stylusDeviceId = 2;
2599
2600 // Stylus down on the window
2601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2602 .deviceId(stylusDeviceId)
2603 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2604 .build());
2605 window->consumeMotionEvent(
2606 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2607
2608 // Touch down on window
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2612 .build());
2613 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2614 .deviceId(touchDeviceId)
2615 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2616 .build());
2617 window->consumeMotionEvent(
2618 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2619 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2620 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2621 // Subsequent stylus movements are ignored
2622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2623 .deviceId(stylusDeviceId)
2624 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2625 .build());
2626 window->assertNoEvents();
2627}
2628
2629/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002630 * Two windows: a window on the left and a window on the right.
2631 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2632 * down. Then, on the left window, also place second touch pointer down.
2633 * This test tries to reproduce a crash.
2634 * In the buggy implementation, second pointer down on the left window would cause a crash.
2635 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002636TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002637 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2638 sp<FakeWindowHandle> leftWindow =
2639 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2640 leftWindow->setFrame(Rect(0, 0, 200, 200));
2641
2642 sp<FakeWindowHandle> rightWindow =
2643 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2644 rightWindow->setFrame(Rect(200, 0, 400, 200));
2645
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002646 mDispatcher->onWindowInfosChanged(
2647 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002648
2649 const int32_t touchDeviceId = 4;
2650 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002651
2652 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002653 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2654 .deviceId(mouseDeviceId)
2655 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2656 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002657 leftWindow->consumeMotionEvent(
2658 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2659
2660 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2662 .deviceId(mouseDeviceId)
2663 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2664 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2665 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002666
2667 leftWindow->consumeMotionEvent(
2668 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2669 leftWindow->consumeMotionEvent(
2670 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2671
Prabir Pradhan678438e2023-04-13 19:32:51 +00002672 mDispatcher->notifyMotion(
2673 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2674 .deviceId(mouseDeviceId)
2675 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2676 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2677 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2678 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002679 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2680
2681 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002682 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2683 .deviceId(touchDeviceId)
2684 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2685 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002686 leftWindow->consumeMotionEvent(
2687 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002688 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2689
2690 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002691 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2692 .deviceId(touchDeviceId)
2693 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2694 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2695 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002696 leftWindow->consumeMotionEvent(
2697 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2698 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2699 // current implementation.
2700 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2701 rightWindow->consumeMotionEvent(
2702 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2703
2704 leftWindow->assertNoEvents();
2705 rightWindow->assertNoEvents();
2706}
2707
2708/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002709 * Two windows: a window on the left and a window on the right.
2710 * Mouse is hovered on the left window and stylus is hovered on the right window.
2711 */
2712TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2714 sp<FakeWindowHandle> leftWindow =
2715 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2716 leftWindow->setFrame(Rect(0, 0, 200, 200));
2717
2718 sp<FakeWindowHandle> rightWindow =
2719 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2720 rightWindow->setFrame(Rect(200, 0, 400, 200));
2721
2722 mDispatcher->onWindowInfosChanged(
2723 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2724
2725 const int32_t stylusDeviceId = 3;
2726 const int32_t mouseDeviceId = 6;
2727
2728 // Start hovering over the left window
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2730 .deviceId(mouseDeviceId)
2731 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2732 .build());
2733 leftWindow->consumeMotionEvent(
2734 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2735
2736 // Stylus hovered on right window
2737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2738 .deviceId(stylusDeviceId)
2739 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2740 .build());
2741 leftWindow->consumeMotionEvent(
2742 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2743 rightWindow->consumeMotionEvent(
2744 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2745
2746 // Subsequent HOVER_MOVE events are dispatched correctly.
2747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2748 .deviceId(mouseDeviceId)
2749 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2750 .build());
2751 leftWindow->consumeMotionEvent(
2752 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2753 rightWindow->consumeMotionEvent(
2754 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2755
2756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2757 .deviceId(stylusDeviceId)
2758 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2759 .build());
2760 leftWindow->consumeMotionEvent(
2761 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2762 rightWindow->consumeMotionEvent(
2763 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2764
2765 leftWindow->assertNoEvents();
2766 rightWindow->assertNoEvents();
2767}
2768
2769/**
2770 * Three windows: a window on the left and a window on the right.
2771 * And a spy window that's positioned above all of them.
2772 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2773 * Check the stream that's received by the spy.
2774 */
2775TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2777
2778 sp<FakeWindowHandle> spyWindow =
2779 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2780 spyWindow->setFrame(Rect(0, 0, 400, 400));
2781 spyWindow->setTrustedOverlay(true);
2782 spyWindow->setSpy(true);
2783
2784 sp<FakeWindowHandle> leftWindow =
2785 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2786 leftWindow->setFrame(Rect(0, 0, 200, 200));
2787
2788 sp<FakeWindowHandle> rightWindow =
2789 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2790
2791 rightWindow->setFrame(Rect(200, 0, 400, 200));
2792
2793 mDispatcher->onWindowInfosChanged(
2794 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2795
2796 const int32_t stylusDeviceId = 1;
2797 const int32_t touchDeviceId = 2;
2798
2799 // Stylus down on the left window
2800 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2801 .deviceId(stylusDeviceId)
2802 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2803 .build());
2804 leftWindow->consumeMotionEvent(
2805 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2806 spyWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2808
2809 // Touch down on the right window
2810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2811 .deviceId(touchDeviceId)
2812 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2813 .build());
2814 leftWindow->consumeMotionEvent(
2815 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2816 spyWindow->consumeMotionEvent(
2817 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2818 rightWindow->consumeMotionEvent(
2819 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2820 spyWindow->consumeMotionEvent(
2821 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2822
2823 // Stylus movements continue, but are ignored because the touch went down more recently.
2824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2825 .deviceId(stylusDeviceId)
2826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2827 .build());
2828
2829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2830 .deviceId(touchDeviceId)
2831 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2832 .build());
2833 rightWindow->consumeMotionEvent(
2834 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2835 spyWindow->consumeMotionEvent(
2836 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2837
2838 spyWindow->assertNoEvents();
2839 leftWindow->assertNoEvents();
2840 rightWindow->assertNoEvents();
2841}
2842
2843/**
2844 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2845 * both.
2846 * Check hover in left window and touch down in the right window.
2847 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2848 */
2849TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2851
2852 sp<FakeWindowHandle> spyWindow =
2853 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2854 spyWindow->setFrame(Rect(0, 0, 400, 400));
2855 spyWindow->setTrustedOverlay(true);
2856 spyWindow->setSpy(true);
2857
2858 sp<FakeWindowHandle> leftWindow =
2859 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2860 leftWindow->setFrame(Rect(0, 0, 200, 200));
2861
2862 sp<FakeWindowHandle> rightWindow =
2863 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2864 rightWindow->setFrame(Rect(200, 0, 400, 200));
2865
2866 mDispatcher->onWindowInfosChanged(
2867 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2868
2869 const int32_t stylusDeviceId = 1;
2870 const int32_t touchDeviceId = 2;
2871
2872 // Stylus hover on the left window
2873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2874 .deviceId(stylusDeviceId)
2875 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2876 .build());
2877 leftWindow->consumeMotionEvent(
2878 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2879 spyWindow->consumeMotionEvent(
2880 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2881
2882 // Touch down on the right window.
2883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2884 .deviceId(touchDeviceId)
2885 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2886 .build());
2887 leftWindow->consumeMotionEvent(
2888 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2889 spyWindow->consumeMotionEvent(
2890 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2891 spyWindow->consumeMotionEvent(
2892 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2893 rightWindow->consumeMotionEvent(
2894 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2895
2896 // Stylus movements continue, but are ignored because the touch is down.
2897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2898 .deviceId(stylusDeviceId)
2899 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2900 .build());
2901
2902 // Touch movements continue. They should be delivered to the right window and to the spy
2903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2904 .deviceId(touchDeviceId)
2905 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2906 .build());
2907 spyWindow->consumeMotionEvent(
2908 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2909 rightWindow->consumeMotionEvent(
2910 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2911
2912 spyWindow->assertNoEvents();
2913 leftWindow->assertNoEvents();
2914 rightWindow->assertNoEvents();
2915}
2916
2917/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002918 * On a single window, use two different devices: mouse and touch.
2919 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2920 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2921 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2922 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2923 * represent a new gesture.
2924 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2927 sp<FakeWindowHandle> window =
2928 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2929 window->setFrame(Rect(0, 0, 400, 400));
2930
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002931 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002932
2933 const int32_t touchDeviceId = 4;
2934 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002935
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002936 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2938 .deviceId(touchDeviceId)
2939 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2940 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002941 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002942 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2943 .deviceId(touchDeviceId)
2944 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2945 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2946 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002947 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002948 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2949 .deviceId(touchDeviceId)
2950 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2951 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2952 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002953 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2954 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2955 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2956
2957 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2959 .deviceId(mouseDeviceId)
2960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2961 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2962 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002963
2964 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002965 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002966 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2967
Prabir Pradhan678438e2023-04-13 19:32:51 +00002968 mDispatcher->notifyMotion(
2969 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2970 .deviceId(mouseDeviceId)
2971 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2972 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2973 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2974 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002975 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2976
2977 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002978 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2979 .deviceId(touchDeviceId)
2980 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2981 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2982 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002983 // Since we already canceled this touch gesture, it will be ignored until a completely new
2984 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2985 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2986 // However, mouse movements should continue to work.
2987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2988 .deviceId(mouseDeviceId)
2989 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2990 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2991 .build());
2992 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2993
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002994 window->assertNoEvents();
2995}
2996
2997/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002998 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2999 * the injected event.
3000 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3003 sp<FakeWindowHandle> window =
3004 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3005 window->setFrame(Rect(0, 0, 400, 400));
3006
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003007 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003008
3009 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003010 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3011 // completion.
3012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003013 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003014 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3015 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003016 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003017 .build()));
3018 window->consumeMotionEvent(
3019 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3020
3021 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3022 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003023 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3024 .deviceId(touchDeviceId)
3025 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3026 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003027
3028 window->consumeMotionEvent(
3029 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3030 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3031}
3032
3033/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003034 * This test is similar to the test above, but the sequence of injected events is different.
3035 *
3036 * Two windows: a window on the left and a window on the right.
3037 * Mouse is hovered over the left window.
3038 * Next, we tap on the left window, where the cursor was last seen.
3039 *
3040 * After that, we inject one finger down onto the right window, and then a second finger down onto
3041 * the left window.
3042 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3043 * window (first), and then another on the left window (second).
3044 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3045 * In the buggy implementation, second finger down on the left window would cause a crash.
3046 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003047TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3049 sp<FakeWindowHandle> leftWindow =
3050 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3051 leftWindow->setFrame(Rect(0, 0, 200, 200));
3052
3053 sp<FakeWindowHandle> rightWindow =
3054 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3055 rightWindow->setFrame(Rect(200, 0, 400, 200));
3056
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003057 mDispatcher->onWindowInfosChanged(
3058 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003059
3060 const int32_t mouseDeviceId = 6;
3061 const int32_t touchDeviceId = 4;
3062 // Hover over the left window. Keep the cursor there.
3063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003064 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003065 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3066 AINPUT_SOURCE_MOUSE)
3067 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003068 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003069 .build()));
3070 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3071
3072 // Tap on left window
3073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003074 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003075 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3076 AINPUT_SOURCE_TOUCHSCREEN)
3077 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003078 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003079 .build()));
3080
3081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003082 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003083 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3084 AINPUT_SOURCE_TOUCHSCREEN)
3085 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003086 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003087 .build()));
3088 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3089 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3090 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3091
3092 // First finger down on right window
3093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003094 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003095 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3096 AINPUT_SOURCE_TOUCHSCREEN)
3097 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003098 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003099 .build()));
3100 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3101
3102 // Second finger down on the left window
3103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003104 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003105 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3106 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003107 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3108 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003109 .build()));
3110 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3111 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3112
3113 // No more events
3114 leftWindow->assertNoEvents();
3115 rightWindow->assertNoEvents();
3116}
3117
3118/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003119 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3120 * While the touch is down, new hover events from the stylus device should be ignored. After the
3121 * touch is gone, stylus hovering should start working again.
3122 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003123TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3125 sp<FakeWindowHandle> window =
3126 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3127 window->setFrame(Rect(0, 0, 200, 200));
3128
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003129 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003130
3131 const int32_t stylusDeviceId = 5;
3132 const int32_t touchDeviceId = 4;
3133 // Start hovering with stylus
3134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003135 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003136 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003137 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003138 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003139 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003140 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003141
3142 // Finger down on the window
3143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003144 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003145 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003146 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003147 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003148 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003149 window->consumeMotionEvent(
3150 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3151 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003152
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003153 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003154 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003155 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003156 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3157 AINPUT_SOURCE_STYLUS)
3158 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003159 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003160 .build()));
3161 // No event should be sent. This event should be ignored because a pointer from another device
3162 // is already down.
3163
3164 // Lift up the finger
3165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003166 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003167 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3168 AINPUT_SOURCE_TOUCHSCREEN)
3169 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003170 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003171 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003172 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003173
3174 // Now that the touch is gone, stylus hovering should start working again
3175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003176 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003177 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3178 AINPUT_SOURCE_STYLUS)
3179 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003180 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003181 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003182 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3183 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003184 window->assertNoEvents();
3185}
3186
3187/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003188 * A spy window above a window with no input channel.
3189 * Start hovering with a stylus device, and then tap with it.
3190 * Ensure spy window receives the entire sequence.
3191 */
3192TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3194 sp<FakeWindowHandle> spyWindow =
3195 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3196 spyWindow->setFrame(Rect(0, 0, 200, 200));
3197 spyWindow->setTrustedOverlay(true);
3198 spyWindow->setSpy(true);
3199 sp<FakeWindowHandle> window =
3200 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3201 window->setNoInputChannel(true);
3202 window->setFrame(Rect(0, 0, 200, 200));
3203
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003204 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003205
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003206 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3208 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3209 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003210 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3211 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3213 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3214 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003215 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3216
3217 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003218 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3219 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3220 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003221 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3222
3223 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003224 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3225 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3226 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003227 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3228
3229 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3231 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3232 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003233 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3234 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3236 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3237 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003238 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3239
3240 // No more events
3241 spyWindow->assertNoEvents();
3242 window->assertNoEvents();
3243}
3244
3245/**
3246 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3247 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3248 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3249 * While the mouse is down, new move events from the touch device should be ignored.
3250 */
3251TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3253 sp<FakeWindowHandle> spyWindow =
3254 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3255 spyWindow->setFrame(Rect(0, 0, 200, 200));
3256 spyWindow->setTrustedOverlay(true);
3257 spyWindow->setSpy(true);
3258 sp<FakeWindowHandle> window =
3259 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3260 window->setFrame(Rect(0, 0, 200, 200));
3261
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003262 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003263
3264 const int32_t mouseDeviceId = 7;
3265 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003266
3267 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003268 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3269 .deviceId(mouseDeviceId)
3270 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3271 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003272 spyWindow->consumeMotionEvent(
3273 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3274 window->consumeMotionEvent(
3275 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3276
3277 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3279 .deviceId(touchDeviceId)
3280 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3281 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003282 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3283 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3284 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3285 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3286
Prabir Pradhan678438e2023-04-13 19:32:51 +00003287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3288 .deviceId(touchDeviceId)
3289 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3290 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003291 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3292 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3293
3294 // Pilfer the stream
3295 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3296 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3297
Prabir Pradhan678438e2023-04-13 19:32:51 +00003298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3299 .deviceId(touchDeviceId)
3300 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3301 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003302 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3303
3304 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3306 .deviceId(mouseDeviceId)
3307 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3308 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3309 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003310
3311 spyWindow->consumeMotionEvent(
3312 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3313 spyWindow->consumeMotionEvent(
3314 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3315 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3316
Prabir Pradhan678438e2023-04-13 19:32:51 +00003317 mDispatcher->notifyMotion(
3318 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3319 .deviceId(mouseDeviceId)
3320 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3321 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3322 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3323 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003324 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3325 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3326
3327 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3329 .deviceId(mouseDeviceId)
3330 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3331 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3332 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003333 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3334 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3335
3336 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003337 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3338 .deviceId(touchDeviceId)
3339 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3340 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003341
3342 // No more events
3343 spyWindow->assertNoEvents();
3344 window->assertNoEvents();
3345}
3346
3347/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003348 * On the display, have a single window, and also an area where there's no window.
3349 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3350 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3351 */
3352TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3353 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3354 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003355 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003356
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003357 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003358
3359 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003360 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003361
3362 mDispatcher->waitForIdle();
3363 window->assertNoEvents();
3364
3365 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003366 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003367 mDispatcher->waitForIdle();
3368 window->consumeMotionDown();
3369}
3370
3371/**
3372 * Same test as above, but instead of touching the empty space, the first touch goes to
3373 * non-touchable window.
3374 */
3375TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3377 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003378 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003379 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3380 window1->setTouchable(false);
3381 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003382 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003383 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3384
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003385 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003386
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003387 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003388 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003389
3390 mDispatcher->waitForIdle();
3391 window1->assertNoEvents();
3392 window2->assertNoEvents();
3393
3394 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003395 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003396 mDispatcher->waitForIdle();
3397 window2->consumeMotionDown();
3398}
3399
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003400/**
3401 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3402 * to the event time of the first ACTION_DOWN sent to the particular window.
3403 */
3404TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3406 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003407 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003408 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3409 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003410 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003411 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3412
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003413 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003414
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003415 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003416 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003417
3418 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003419
3420 MotionEvent* motionEvent1 = window1->consumeMotion();
3421 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003422 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003423 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3424 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003425
3426 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003427 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003428 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003429 MotionEvent* motionEvent2 = window2->consumeMotion();
3430 ASSERT_NE(motionEvent2, nullptr);
3431 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003432 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003433 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003434
3435 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003436 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003437 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003438 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003439
3440 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003441 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003442 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003443 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003444
3445 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3446 window1->consumeMotionMove();
3447 window1->assertNoEvents();
3448
3449 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003450 mDispatcher->notifyMotion(
3451 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003452 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003453 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003454
Prabir Pradhan678438e2023-04-13 19:32:51 +00003455 mDispatcher->notifyMotion(
3456 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003457 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003458 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003459}
3460
Garfield Tandf26e862020-07-01 20:18:19 -07003461TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003463 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003464 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003465 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003466 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003467 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003468 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003469
3470 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3471
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003472 mDispatcher->onWindowInfosChanged(
3473 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003474
3475 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003477 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003478 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3479 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003480 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003481 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003482 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003483
3484 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003486 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003487 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3488 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003489 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003490 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003491 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3492 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003493
3494 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003496 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003497 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3498 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003499 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003500 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003501 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3502 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003503
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003505 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003506 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3507 AINPUT_SOURCE_MOUSE)
3508 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3509 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003510 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003511 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003512 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003513
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003515 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003516 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3517 AINPUT_SOURCE_MOUSE)
3518 .buttonState(0)
3519 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003520 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003521 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003522 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003523
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003525 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003526 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3527 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003528 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003529 .build()));
3530 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3531
3532 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003534 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003535 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3536 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003537 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003538 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003539 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003540
3541 // No more events
3542 windowLeft->assertNoEvents();
3543 windowRight->assertNoEvents();
3544}
3545
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003546/**
3547 * Put two fingers down (and don't release them) and click the mouse button.
3548 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3549 * currently active gesture should be canceled, and the new one should proceed.
3550 */
3551TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3553 sp<FakeWindowHandle> window =
3554 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3555 window->setFrame(Rect(0, 0, 600, 800));
3556
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003557 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003558
3559 const int32_t touchDeviceId = 4;
3560 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003561
3562 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3564 .deviceId(touchDeviceId)
3565 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3566 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003567
Prabir Pradhan678438e2023-04-13 19:32:51 +00003568 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3569 .deviceId(touchDeviceId)
3570 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3571 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3572 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003573 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3574 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3575
3576 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3578 .deviceId(mouseDeviceId)
3579 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3580 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3581 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003582 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3583 WithPointerCount(2u)));
3584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3585
Prabir Pradhan678438e2023-04-13 19:32:51 +00003586 mDispatcher->notifyMotion(
3587 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3588 .deviceId(mouseDeviceId)
3589 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3590 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3591 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3592 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003593 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3594
3595 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3596 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003597 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3598 .deviceId(touchDeviceId)
3599 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3600 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3601 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003602 window->assertNoEvents();
3603}
3604
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003605TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3607
3608 sp<FakeWindowHandle> spyWindow =
3609 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3610 spyWindow->setFrame(Rect(0, 0, 600, 800));
3611 spyWindow->setTrustedOverlay(true);
3612 spyWindow->setSpy(true);
3613 sp<FakeWindowHandle> window =
3614 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3615 window->setFrame(Rect(0, 0, 600, 800));
3616
3617 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003618 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003619
3620 // Send mouse cursor to the window
3621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003622 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003623 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3624 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003625 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003626 .build()));
3627
3628 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3629 WithSource(AINPUT_SOURCE_MOUSE)));
3630 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3631 WithSource(AINPUT_SOURCE_MOUSE)));
3632
3633 window->assertNoEvents();
3634 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003635}
3636
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003637TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3639
3640 sp<FakeWindowHandle> spyWindow =
3641 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3642 spyWindow->setFrame(Rect(0, 0, 600, 800));
3643 spyWindow->setTrustedOverlay(true);
3644 spyWindow->setSpy(true);
3645 sp<FakeWindowHandle> window =
3646 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3647 window->setFrame(Rect(0, 0, 600, 800));
3648
3649 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003650 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003651
3652 // Send mouse cursor to the window
3653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003654 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003655 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3656 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003657 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003658 .build()));
3659
3660 // Move mouse cursor
3661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003662 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003663 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3664 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003665 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003666 .build()));
3667
3668 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3669 WithSource(AINPUT_SOURCE_MOUSE)));
3670 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3671 WithSource(AINPUT_SOURCE_MOUSE)));
3672 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3673 WithSource(AINPUT_SOURCE_MOUSE)));
3674 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3675 WithSource(AINPUT_SOURCE_MOUSE)));
3676 // Touch down on the window
3677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003678 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003679 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3680 AINPUT_SOURCE_TOUCHSCREEN)
3681 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003682 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003683 .build()));
3684 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3685 WithSource(AINPUT_SOURCE_MOUSE)));
3686 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3687 WithSource(AINPUT_SOURCE_MOUSE)));
3688 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3689 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3690 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3691 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3692
3693 // pilfer the motion, retaining the gesture on the spy window.
3694 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3695 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3696 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3697
3698 // Touch UP on the window
3699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003700 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003701 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3702 AINPUT_SOURCE_TOUCHSCREEN)
3703 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003704 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003705 .build()));
3706 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3707 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3708
3709 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3710 // to send a new gesture. It should again go to both windows (spy and the window below), just
3711 // like the first gesture did, before pilfering. The window configuration has not changed.
3712
3713 // One more tap - DOWN
3714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003715 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003716 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3717 AINPUT_SOURCE_TOUCHSCREEN)
3718 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003719 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003720 .build()));
3721 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3722 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3723 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3724 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3725
3726 // Touch UP on the window
3727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003728 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003729 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3730 AINPUT_SOURCE_TOUCHSCREEN)
3731 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003732 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003733 .build()));
3734 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3735 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3736 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3737 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3738
3739 window->assertNoEvents();
3740 spyWindow->assertNoEvents();
3741}
3742
Garfield Tandf26e862020-07-01 20:18:19 -07003743// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3744// directly in this test.
3745TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003747 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003748 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003749 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003750
3751 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3752
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003754
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003756 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003757 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3758 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003759 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003760 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003761 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003762 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003764 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003765 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3766 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003767 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003768 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003769 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3770 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003771
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003773 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003774 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3775 AINPUT_SOURCE_MOUSE)
3776 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3777 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003778 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003779 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003780 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003781
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003783 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003784 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3785 AINPUT_SOURCE_MOUSE)
3786 .buttonState(0)
3787 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003788 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003789 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003790 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003791
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003793 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003794 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3795 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003796 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003797 .build()));
3798 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3799
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003800 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3801 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3802 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003803 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003804 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3805 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003806 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003807 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003808 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003809}
3810
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003811/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003812 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3813 * is generated.
3814 */
3815TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3817 sp<FakeWindowHandle> window =
3818 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3819 window->setFrame(Rect(0, 0, 1200, 800));
3820
3821 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3822
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003824
3825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003826 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003827 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3828 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003829 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003830 .build()));
3831 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3832
3833 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003834 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003835 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3836}
3837
3838/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003839 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3840 */
3841TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3842 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3843 sp<FakeWindowHandle> window =
3844 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3845 window->setFrame(Rect(0, 0, 1200, 800));
3846
3847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3848
3849 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3850
3851 MotionEventBuilder hoverEnterBuilder =
3852 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3853 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3854 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3856 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3858 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3859 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3860 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3861}
3862
3863/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003864 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3865 */
3866TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3868 sp<FakeWindowHandle> window =
3869 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3870 window->setFrame(Rect(0, 0, 100, 100));
3871
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003872 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003873
3874 const int32_t mouseDeviceId = 7;
3875 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003876
3877 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003878 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3879 .deviceId(mouseDeviceId)
3880 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3881 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003882 window->consumeMotionEvent(
3883 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3884
3885 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3887 .deviceId(touchDeviceId)
3888 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3889 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003890
3891 window->consumeMotionEvent(
3892 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3893 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3894}
3895
3896/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003897 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003898 * The tap causes a HOVER_EXIT event to be generated because the current event
3899 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003900 */
3901TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3903 sp<FakeWindowHandle> window =
3904 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3905 window->setFrame(Rect(0, 0, 100, 100));
3906
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003907 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003908 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3909 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3910 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003911 ASSERT_NO_FATAL_FAILURE(
3912 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3913 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003914
3915 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3917 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3918 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003919 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003920 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3921 WithSource(AINPUT_SOURCE_MOUSE))));
3922
3923 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003924 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3925 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3926
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003927 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3928 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3929 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003930 ASSERT_NO_FATAL_FAILURE(
3931 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3932 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3933}
3934
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003935TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3937 sp<FakeWindowHandle> windowDefaultDisplay =
3938 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3939 ADISPLAY_ID_DEFAULT);
3940 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3941 sp<FakeWindowHandle> windowSecondDisplay =
3942 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3943 SECOND_DISPLAY_ID);
3944 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3945
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003946 mDispatcher->onWindowInfosChanged(
3947 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003948
3949 // Set cursor position in window in default display and check that hover enter and move
3950 // events are generated.
3951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003952 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003953 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3954 AINPUT_SOURCE_MOUSE)
3955 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003956 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003957 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003958 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003959
3960 // Remove all windows in secondary display and check that no event happens on window in
3961 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003962 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3963
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003964 windowDefaultDisplay->assertNoEvents();
3965
3966 // Move cursor position in window in default display and check that only hover move
3967 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003968 mDispatcher->onWindowInfosChanged(
3969 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003971 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003972 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3973 AINPUT_SOURCE_MOUSE)
3974 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003975 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003976 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003977 windowDefaultDisplay->consumeMotionEvent(
3978 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3979 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003980 windowDefaultDisplay->assertNoEvents();
3981}
3982
Garfield Tan00f511d2019-06-12 16:55:40 -07003983TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003985
3986 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003987 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003988 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003989 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003990 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003991 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003992
3993 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3994
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003995 mDispatcher->onWindowInfosChanged(
3996 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003997
3998 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3999 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004001 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004002 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004003 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004004 windowRight->assertNoEvents();
4005}
4006
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004007TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004009 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4010 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004011 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004012
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004013 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004014 setFocusedWindow(window);
4015
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004016 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004017
Prabir Pradhan678438e2023-04-13 19:32:51 +00004018 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004019
4020 // Window should receive key down event.
4021 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4022
4023 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4024 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004025 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004026 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004027 AKEY_EVENT_FLAG_CANCELED);
4028}
4029
4030TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004032 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4033 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004034
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004035 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004036
Prabir Pradhan678438e2023-04-13 19:32:51 +00004037 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4038 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004039
4040 // Window should receive motion down event.
4041 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4042
4043 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4044 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004045 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004046 window->consumeMotionEvent(
4047 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004048}
4049
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004050TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4052 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4053 "Fake Window", ADISPLAY_ID_DEFAULT);
4054
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004055 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004056
4057 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4058 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4059 .build());
4060
4061 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4062
4063 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4064 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4065 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4066
4067 // After the device has been reset, a new hovering stream can be sent to the window
4068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4069 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4070 .build());
4071 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4072}
4073
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004074TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004076 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4077 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004078 window->setFocusable(true);
4079
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004080 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004081 setFocusedWindow(window);
4082
4083 window->consumeFocusEvent(true);
4084
Prabir Pradhan678438e2023-04-13 19:32:51 +00004085 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004086 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4087 const nsecs_t injectTime = keyArgs.eventTime;
4088 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004089 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004090 // The dispatching time should be always greater than or equal to intercept key timeout.
4091 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4092 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4093 std::chrono::nanoseconds(interceptKeyTimeout).count());
4094}
4095
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004096/**
4097 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4098 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004099TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004101 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4102 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004103 window->setFocusable(true);
4104
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004105 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004106 setFocusedWindow(window);
4107
4108 window->consumeFocusEvent(true);
4109
Prabir Pradhan678438e2023-04-13 19:32:51 +00004110 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004111 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004112
4113 // Set a value that's significantly larger than the default consumption timeout. If the
4114 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4115 mFakePolicy->setInterceptKeyTimeout(600ms);
4116 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4117 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004118 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4119}
4120
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004121/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004122 * Two windows. First is a regular window. Second does not overlap with the first, and has
4123 * WATCH_OUTSIDE_TOUCH.
4124 * Both windows are owned by the same UID.
4125 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4126 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4127 */
4128TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4129 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004130 sp<FakeWindowHandle> window =
4131 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004132 window->setFrame(Rect{0, 0, 100, 100});
4133
4134 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004135 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004136 ADISPLAY_ID_DEFAULT);
4137 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4138 outsideWindow->setWatchOutsideTouch(true);
4139 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004140 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004141
4142 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004143 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4144 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4145 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004146 window->consumeMotionDown();
4147 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4148 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4149 outsideWindow->consumeMotionEvent(
4150 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4151}
4152
4153/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004154 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4155 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4156 * ACTION_OUTSIDE event is sent per gesture.
4157 */
4158TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4159 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004161 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4162 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004163 window->setWatchOutsideTouch(true);
4164 window->setFrame(Rect{0, 0, 100, 100});
4165 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004166 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4167 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004168 secondWindow->setFrame(Rect{100, 100, 200, 200});
4169 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004170 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4171 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004172 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004173 mDispatcher->onWindowInfosChanged(
4174 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004175
4176 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004177 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4178 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4179 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004180 window->assertNoEvents();
4181 secondWindow->assertNoEvents();
4182
4183 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4184 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004185 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4186 ADISPLAY_ID_DEFAULT,
4187 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004188 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4189 window->consumeMotionEvent(
4190 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004191 secondWindow->consumeMotionDown();
4192 thirdWindow->assertNoEvents();
4193
4194 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4195 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004196 mDispatcher->notifyMotion(
4197 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4198 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004199 window->assertNoEvents();
4200 secondWindow->consumeMotionMove();
4201 thirdWindow->consumeMotionDown();
4202}
4203
Prabir Pradhan814fe082022-07-22 20:22:18 +00004204TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004206 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4207 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004208 window->setFocusable(true);
4209
Patrick Williamsd828f302023-04-28 17:52:08 -05004210 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004211 setFocusedWindow(window);
4212
4213 window->consumeFocusEvent(true);
4214
Prabir Pradhan678438e2023-04-13 19:32:51 +00004215 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4216 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4217 mDispatcher->notifyKey(keyDown);
4218 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004219
4220 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4221 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4222
4223 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004224 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004225
4226 window->consumeFocusEvent(false);
4227
Prabir Pradhan678438e2023-04-13 19:32:51 +00004228 mDispatcher->notifyKey(keyDown);
4229 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004230 window->assertNoEvents();
4231}
4232
Arthur Hung96483742022-11-15 03:30:48 +00004233TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4235 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4236 "Fake Window", ADISPLAY_ID_DEFAULT);
4237 // Ensure window is non-split and have some transform.
4238 window->setPreventSplitting(true);
4239 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004240 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004241
4242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004244 {50, 50}))
4245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4246 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4247
4248 const MotionEvent secondFingerDownEvent =
4249 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4250 .displayId(ADISPLAY_ID_DEFAULT)
4251 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004252 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4253 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004254 .build();
4255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004256 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004257 InputEventInjectionSync::WAIT_FOR_RESULT))
4258 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4259
4260 const MotionEvent* event = window->consumeMotion();
4261 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4262 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4263 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4264 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4265 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4266}
4267
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004268/**
4269 * Two windows: a splittable and a non-splittable.
4270 * The non-splittable window shouldn't receive any "incomplete" gestures.
4271 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4272 * The second pointer should be dropped because the initial window is splittable, so it won't get
4273 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4274 * "incomplete" gestures.
4275 */
4276TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4278 sp<FakeWindowHandle> leftWindow =
4279 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4280 ADISPLAY_ID_DEFAULT);
4281 leftWindow->setPreventSplitting(false);
4282 leftWindow->setFrame(Rect(0, 0, 100, 100));
4283 sp<FakeWindowHandle> rightWindow =
4284 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4285 ADISPLAY_ID_DEFAULT);
4286 rightWindow->setPreventSplitting(true);
4287 rightWindow->setFrame(Rect(100, 100, 200, 200));
4288 mDispatcher->onWindowInfosChanged(
4289 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4290
4291 // Touch down on left, splittable window
4292 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4293 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4294 .build());
4295 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4296
4297 mDispatcher->notifyMotion(
4298 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4299 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4300 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4301 .build());
4302 leftWindow->assertNoEvents();
4303 rightWindow->assertNoEvents();
4304}
4305
Harry Cuttsb166c002023-05-09 13:06:05 +00004306TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4308 sp<FakeWindowHandle> window =
4309 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4310 window->setFrame(Rect(0, 0, 400, 400));
4311 sp<FakeWindowHandle> trustedOverlay =
4312 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4313 ADISPLAY_ID_DEFAULT);
4314 trustedOverlay->setSpy(true);
4315 trustedOverlay->setTrustedOverlay(true);
4316
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004317 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004318
4319 // Start a three-finger touchpad swipe
4320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4321 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4322 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4323 .build());
4324 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4325 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4326 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4327 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4328 .build());
4329 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4330 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4331 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4332 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4333 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4334 .build());
4335
4336 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4337 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4338 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4339
4340 // Move the swipe a bit
4341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4342 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4343 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4344 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4345 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4346 .build());
4347
4348 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4349
4350 // End the swipe
4351 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4352 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4353 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4354 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4355 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4356 .build());
4357 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4358 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4359 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4360 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4361 .build());
4362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4363 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4364 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4365 .build());
4366
4367 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4368 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4369 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4370
4371 window->assertNoEvents();
4372}
4373
4374TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4376 sp<FakeWindowHandle> window =
4377 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4378 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004380
4381 // Start a three-finger touchpad swipe
4382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4383 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4384 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4385 .build());
4386 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4387 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4388 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4389 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4390 .build());
4391 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4392 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4393 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4394 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4395 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4396 .build());
4397
4398 // Move the swipe a bit
4399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4400 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4401 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4402 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4403 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4404 .build());
4405
4406 // End the swipe
4407 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4408 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4409 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4410 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4411 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4412 .build());
4413 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4414 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4415 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4416 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4417 .build());
4418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4419 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4420 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4421 .build());
4422
4423 window->assertNoEvents();
4424}
4425
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004426/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004427 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4428 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004429 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004430 */
4431TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4433 sp<FakeWindowHandle> window =
4434 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4435 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004436 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004437
4438 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4439 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4440 .downTime(baseTime + 10)
4441 .eventTime(baseTime + 10)
4442 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4443 .build());
4444
4445 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4446
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004447 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004448 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004449
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004450 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004451
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004452 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4453 .downTime(baseTime + 10)
4454 .eventTime(baseTime + 30)
4455 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4456 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4457 .build());
4458
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004459 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4460
4461 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004462 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4463 .downTime(baseTime + 10)
4464 .eventTime(baseTime + 40)
4465 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4466 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4467 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004468
4469 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4470
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4472 .downTime(baseTime + 10)
4473 .eventTime(baseTime + 50)
4474 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4475 .build());
4476
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004477 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4478
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4480 .downTime(baseTime + 60)
4481 .eventTime(baseTime + 60)
4482 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4483 .build());
4484
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004485 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004486}
4487
4488/**
Hu Guo771a7692023-09-17 20:51:08 +08004489 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4490 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4491 * its coordinates should be converted by the transform of the windows of target screen.
4492 */
4493TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4494 // This case will create a window and a spy window on the default display and mirror
4495 // window on the second display. cancel event is sent through spy window pilferPointers
4496 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4497
4498 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4499 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4500 spyWindowDefaultDisplay->setTrustedOverlay(true);
4501 spyWindowDefaultDisplay->setSpy(true);
4502
4503 sp<FakeWindowHandle> windowDefaultDisplay =
4504 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4505 ADISPLAY_ID_DEFAULT);
4506 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4507
4508 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4509 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4510
4511 // Add the windows to the dispatcher
4512 mDispatcher->onWindowInfosChanged(
4513 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4514 *windowSecondDisplay->getInfo()},
4515 {},
4516 0,
4517 0});
4518
4519 // Send down to ADISPLAY_ID_DEFAULT
4520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4521 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4522 {100, 100}))
4523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4524
4525 spyWindowDefaultDisplay->consumeMotionDown();
4526 windowDefaultDisplay->consumeMotionDown();
4527
4528 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4529
4530 // windowDefaultDisplay gets cancel
4531 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4532 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4533
4534 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4535 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4536 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4537 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4538 EXPECT_EQ(100, event->getX(0));
4539 EXPECT_EQ(100, event->getY(0));
4540}
4541
4542/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004543 * Ensure the correct coordinate spaces are used by InputDispatcher.
4544 *
4545 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4546 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4547 * space.
4548 */
4549class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4550public:
4551 void SetUp() override {
4552 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004553 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004554 }
4555
4556 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4557 gui::DisplayInfo info;
4558 info.displayId = displayId;
4559 info.transform = transform;
4560 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004561 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004562 }
4563
4564 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4565 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004566 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004567 }
4568
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004569 void removeAllWindowsAndDisplays() {
4570 mDisplayInfos.clear();
4571 mWindowInfos.clear();
4572 }
4573
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004574 // Set up a test scenario where the display has a scaled projection and there are two windows
4575 // on the display.
4576 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4577 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4578 // respectively.
4579 ui::Transform displayTransform;
4580 displayTransform.set(2, 0, 0, 4);
4581 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4582
4583 std::shared_ptr<FakeApplicationHandle> application =
4584 std::make_shared<FakeApplicationHandle>();
4585
4586 // Add two windows to the display. Their frames are represented in the display space.
4587 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004588 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4589 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004590 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4591 addWindow(firstWindow);
4592
4593 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004594 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4595 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004596 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4597 addWindow(secondWindow);
4598 return {std::move(firstWindow), std::move(secondWindow)};
4599 }
4600
4601private:
4602 std::vector<gui::DisplayInfo> mDisplayInfos;
4603 std::vector<gui::WindowInfo> mWindowInfos;
4604};
4605
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004606TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004607 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4608 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004609 // selected so that if the hit test was performed with the point and the bounds being in
4610 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004611 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4612 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4613 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004614
4615 firstWindow->consumeMotionDown();
4616 secondWindow->assertNoEvents();
4617}
4618
4619// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4620// the event should be treated as being in the logical display space.
4621TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4622 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4623 // Send down to the first window. The point is represented in the logical display space. The
4624 // point is selected so that if the hit test was done in logical display space, then it would
4625 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004626 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004627 PointF{75 * 2, 55 * 4});
4628
4629 firstWindow->consumeMotionDown();
4630 secondWindow->assertNoEvents();
4631}
4632
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004633// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4634// event should be treated as being in the logical display space.
4635TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4636 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4637
4638 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4639 ui::Transform injectedEventTransform;
4640 injectedEventTransform.set(matrix);
4641 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4642 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4643
4644 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4645 .displayId(ADISPLAY_ID_DEFAULT)
4646 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004647 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004648 .x(untransformedPoint.x)
4649 .y(untransformedPoint.y))
4650 .build();
4651 event.transform(matrix);
4652
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004653 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004654 InputEventInjectionSync::WAIT_FOR_RESULT);
4655
4656 firstWindow->consumeMotionDown();
4657 secondWindow->assertNoEvents();
4658}
4659
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004660TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4661 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4662
4663 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004664 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4665 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4666 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004667
4668 firstWindow->assertNoEvents();
4669 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004670 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004671 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4672
4673 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4674 EXPECT_EQ(300, event->getRawX(0));
4675 EXPECT_EQ(880, event->getRawY(0));
4676
4677 // Ensure that the x and y values are in the window's coordinate space.
4678 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4679 // the logical display space. This will be the origin of the window space.
4680 EXPECT_EQ(100, event->getX(0));
4681 EXPECT_EQ(80, event->getY(0));
4682}
4683
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004684TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4685 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4686 // The monitor will always receive events in the logical display's coordinate space, because
4687 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004688 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004689
4690 // Send down to the first window.
4691 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4692 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4693 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4694 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4695
4696 // Second pointer goes down on second window.
4697 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4698 ADISPLAY_ID_DEFAULT,
4699 {PointF{50, 100}, PointF{150, 220}}));
4700 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4701 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4702 {1, PointF{300, 880}}};
4703 monitor.consumeMotionEvent(
4704 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4705
4706 mDispatcher->cancelCurrentTouch();
4707
4708 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4709 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4710 monitor.consumeMotionEvent(
4711 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4712}
4713
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004714TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4715 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4716
4717 // Send down to the first window.
4718 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4719 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4720 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4721
4722 // The pointer is transferred to the second window, and the second window receives it in the
4723 // correct coordinate space.
4724 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4725 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4726 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4727}
4728
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004729TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4730 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4731
4732 // Send hover move to the second window, and ensure it shows up as hover enter.
4733 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4734 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4735 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4736 WithCoords(100, 80), WithRawCoords(300, 880)));
4737
4738 // Touch down at the same location and ensure a hover exit is synthesized.
4739 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4740 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4741 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4742 WithRawCoords(300, 880)));
4743 secondWindow->consumeMotionEvent(
4744 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4745 secondWindow->assertNoEvents();
4746 firstWindow->assertNoEvents();
4747}
4748
4749TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4750 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4751
4752 // Send hover enter to second window
4753 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4754 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4755 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4756 WithCoords(100, 80), WithRawCoords(300, 880)));
4757
4758 mDispatcher->cancelCurrentTouch();
4759
4760 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4761 WithRawCoords(300, 880)));
4762 secondWindow->assertNoEvents();
4763 firstWindow->assertNoEvents();
4764}
4765
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004766/** Ensure consistent behavior of InputDispatcher in all orientations. */
4767class InputDispatcherDisplayOrientationFixture
4768 : public InputDispatcherDisplayProjectionTest,
4769 public ::testing::WithParamInterface<ui::Rotation> {};
4770
4771// This test verifies the touchable region of a window for all rotations of the display by tapping
4772// in different locations on the display, specifically points close to the four corners of a
4773// window.
4774TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4775 constexpr static int32_t displayWidth = 400;
4776 constexpr static int32_t displayHeight = 800;
4777
4778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4779
4780 const auto rotation = GetParam();
4781
4782 // Set up the display with the specified rotation.
4783 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4784 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4785 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4786 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4787 logicalDisplayWidth, logicalDisplayHeight);
4788 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4789
4790 // Create a window with its bounds determined in the logical display.
4791 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4792 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4793 sp<FakeWindowHandle> window =
4794 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4795 window->setFrame(frameInDisplay, displayTransform);
4796 addWindow(window);
4797
4798 // The following points in logical display space should be inside the window.
4799 static const std::array<vec2, 4> insidePoints{
4800 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4801 for (const auto pointInsideWindow : insidePoints) {
4802 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4803 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004804 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4805 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4806 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004807 window->consumeMotionDown();
4808
Prabir Pradhan678438e2023-04-13 19:32:51 +00004809 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4810 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4811 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004812 window->consumeMotionUp();
4813 }
4814
4815 // The following points in logical display space should be outside the window.
4816 static const std::array<vec2, 5> outsidePoints{
4817 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4818 for (const auto pointOutsideWindow : outsidePoints) {
4819 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4820 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004821 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4822 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4823 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004824
Prabir Pradhan678438e2023-04-13 19:32:51 +00004825 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4826 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4827 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004828 }
4829 window->assertNoEvents();
4830}
4831
4832// Run the precision tests for all rotations.
4833INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4834 InputDispatcherDisplayOrientationFixture,
4835 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4836 ui::ROTATION_270),
4837 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4838 return ftl::enum_string(testParamInfo.param);
4839 });
4840
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004841using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4842 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004843
4844class TransferTouchFixture : public InputDispatcherTest,
4845 public ::testing::WithParamInterface<TransferFunction> {};
4846
4847TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004849
4850 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004851 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004852 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4853 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004854 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004855 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004856 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4857 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004858 sp<FakeWindowHandle> wallpaper =
4859 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4860 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004861 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004862 mDispatcher->onWindowInfosChanged(
4863 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004864
4865 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004866 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4867 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004868
Svet Ganov5d3bc372020-01-26 23:11:07 -08004869 // Only the first window should get the down event
4870 firstWindow->consumeMotionDown();
4871 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004872 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004873
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004874 // Transfer touch to the second window
4875 TransferFunction f = GetParam();
4876 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4877 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004878 // The first window gets cancel and the second gets down
4879 firstWindow->consumeMotionCancel();
4880 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004881 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004882
4883 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004884 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4885 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004886 // The first window gets no events and the second gets up
4887 firstWindow->assertNoEvents();
4888 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004889 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004890}
4891
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004892/**
4893 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4894 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4895 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4896 * natural to the user.
4897 * In this test, we are sending a pointer to both spy window and first window. We then try to
4898 * transfer touch to the second window. The dispatcher should identify the first window as the
4899 * one that should lose the gesture, and therefore the action should be to move the gesture from
4900 * the first window to the second.
4901 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4902 * the other API, as well.
4903 */
4904TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4906
4907 // Create a couple of windows + a spy window
4908 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004909 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004910 spyWindow->setTrustedOverlay(true);
4911 spyWindow->setSpy(true);
4912 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004913 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004914 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004915 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004916
4917 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004918 mDispatcher->onWindowInfosChanged(
4919 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004920
4921 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004922 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4923 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004924 // Only the first window and spy should get the down event
4925 spyWindow->consumeMotionDown();
4926 firstWindow->consumeMotionDown();
4927
4928 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4929 // if f === 'transferTouch'.
4930 TransferFunction f = GetParam();
4931 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4932 ASSERT_TRUE(success);
4933 // The first window gets cancel and the second gets down
4934 firstWindow->consumeMotionCancel();
4935 secondWindow->consumeMotionDown();
4936
4937 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004938 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4939 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004940 // The first window gets no events and the second+spy get up
4941 firstWindow->assertNoEvents();
4942 spyWindow->consumeMotionUp();
4943 secondWindow->consumeMotionUp();
4944}
4945
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004946TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004948
4949 PointF touchPoint = {10, 10};
4950
4951 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004952 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004953 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4954 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004955 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004956 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004957 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4958 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004959 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004960
4961 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004962 mDispatcher->onWindowInfosChanged(
4963 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004964
4965 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004966 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4967 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4968 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004969 // Only the first window should get the down event
4970 firstWindow->consumeMotionDown();
4971 secondWindow->assertNoEvents();
4972
4973 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004974 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4975 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004976 // Only the first window should get the pointer down event
4977 firstWindow->consumeMotionPointerDown(1);
4978 secondWindow->assertNoEvents();
4979
4980 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004981 TransferFunction f = GetParam();
4982 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4983 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004984 // The first window gets cancel and the second gets down and pointer down
4985 firstWindow->consumeMotionCancel();
4986 secondWindow->consumeMotionDown();
4987 secondWindow->consumeMotionPointerDown(1);
4988
4989 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004990 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4991 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004992 // The first window gets nothing and the second gets pointer up
4993 firstWindow->assertNoEvents();
4994 secondWindow->consumeMotionPointerUp(1);
4995
4996 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004997 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4998 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004999 // The first window gets nothing and the second gets up
5000 firstWindow->assertNoEvents();
5001 secondWindow->consumeMotionUp();
5002}
5003
Arthur Hungc539dbb2022-12-08 07:45:36 +00005004TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5005 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5006
5007 // Create a couple of windows
5008 sp<FakeWindowHandle> firstWindow =
5009 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5010 ADISPLAY_ID_DEFAULT);
5011 firstWindow->setDupTouchToWallpaper(true);
5012 sp<FakeWindowHandle> secondWindow =
5013 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5014 ADISPLAY_ID_DEFAULT);
5015 secondWindow->setDupTouchToWallpaper(true);
5016
5017 sp<FakeWindowHandle> wallpaper1 =
5018 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5019 wallpaper1->setIsWallpaper(true);
5020
5021 sp<FakeWindowHandle> wallpaper2 =
5022 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5023 wallpaper2->setIsWallpaper(true);
5024 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005025 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5026 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5027 {},
5028 0,
5029 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005030
5031 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005032 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5033 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005034
5035 // Only the first window should get the down event
5036 firstWindow->consumeMotionDown();
5037 secondWindow->assertNoEvents();
5038 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5039 wallpaper2->assertNoEvents();
5040
5041 // Transfer touch focus to the second window
5042 TransferFunction f = GetParam();
5043 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5044 ASSERT_TRUE(success);
5045
5046 // The first window gets cancel and the second gets down
5047 firstWindow->consumeMotionCancel();
5048 secondWindow->consumeMotionDown();
5049 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5050 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5051
5052 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005053 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5054 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005055 // The first window gets no events and the second gets up
5056 firstWindow->assertNoEvents();
5057 secondWindow->consumeMotionUp();
5058 wallpaper1->assertNoEvents();
5059 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5060}
5061
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005062// For the cases of single pointer touch and two pointers non-split touch, the api's
5063// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5064// for the case where there are multiple pointers split across several windows.
5065INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5066 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005067 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5068 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005069 return dispatcher->transferTouch(destChannelToken,
5070 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005071 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005072 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5073 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005074 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005075 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005076 }));
5077
Svet Ganov5d3bc372020-01-26 23:11:07 -08005078TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005080
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005081 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005082 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5083 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005084 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005085
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005086 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005087 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5088 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005089 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005090
5091 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005092 mDispatcher->onWindowInfosChanged(
5093 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005094
5095 PointF pointInFirst = {300, 200};
5096 PointF pointInSecond = {300, 600};
5097
5098 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005099 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5100 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5101 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005102 // Only the first window should get the down event
5103 firstWindow->consumeMotionDown();
5104 secondWindow->assertNoEvents();
5105
5106 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005107 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5108 ADISPLAY_ID_DEFAULT,
5109 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005110 // The first window gets a move and the second a down
5111 firstWindow->consumeMotionMove();
5112 secondWindow->consumeMotionDown();
5113
5114 // Transfer touch focus to the second window
5115 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5116 // The first window gets cancel and the new gets pointer down (it already saw down)
5117 firstWindow->consumeMotionCancel();
5118 secondWindow->consumeMotionPointerDown(1);
5119
5120 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005121 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5122 ADISPLAY_ID_DEFAULT,
5123 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005124 // The first window gets nothing and the second gets pointer up
5125 firstWindow->assertNoEvents();
5126 secondWindow->consumeMotionPointerUp(1);
5127
5128 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005129 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5130 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005131 // The first window gets nothing and the second gets up
5132 firstWindow->assertNoEvents();
5133 secondWindow->consumeMotionUp();
5134}
5135
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005136// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5137// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5138// touch is not supported, so the touch should continue on those windows and the transferred-to
5139// window should get nothing.
5140TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5142
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005143 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005144 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5145 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005146 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005147
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005148 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005149 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5150 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005151 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005152
5153 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005154 mDispatcher->onWindowInfosChanged(
5155 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005156
5157 PointF pointInFirst = {300, 200};
5158 PointF pointInSecond = {300, 600};
5159
5160 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005161 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5162 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5163 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005164 // Only the first window should get the down event
5165 firstWindow->consumeMotionDown();
5166 secondWindow->assertNoEvents();
5167
5168 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005169 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5170 ADISPLAY_ID_DEFAULT,
5171 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005172 // The first window gets a move and the second a down
5173 firstWindow->consumeMotionMove();
5174 secondWindow->consumeMotionDown();
5175
5176 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005177 const bool transferred =
5178 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005179 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5180 ASSERT_FALSE(transferred);
5181 firstWindow->assertNoEvents();
5182 secondWindow->assertNoEvents();
5183
5184 // The rest of the dispatch should proceed as normal
5185 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005186 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5187 ADISPLAY_ID_DEFAULT,
5188 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005189 // The first window gets MOVE and the second gets pointer up
5190 firstWindow->consumeMotionMove();
5191 secondWindow->consumeMotionUp();
5192
5193 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005194 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5195 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005196 // The first window gets nothing and the second gets up
5197 firstWindow->consumeMotionUp();
5198 secondWindow->assertNoEvents();
5199}
5200
Arthur Hungabbb9d82021-09-01 14:52:30 +00005201// This case will create two windows and one mirrored window on the default display and mirror
5202// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5203// the windows info of second display before default display.
5204TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5206 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005207 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005208 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005209 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005210 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005211 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005212
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005213 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005214 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005215
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005216 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005217 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005218
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005219 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005220 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005221
5222 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005223 mDispatcher->onWindowInfosChanged(
5224 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5225 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5226 *secondWindowInPrimary->getInfo()},
5227 {},
5228 0,
5229 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005230
5231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005232 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005233 {50, 50}))
5234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5235
5236 // Window should receive motion event.
5237 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5238
5239 // Transfer touch focus
5240 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5241 secondWindowInPrimary->getToken()));
5242 // The first window gets cancel.
5243 firstWindowInPrimary->consumeMotionCancel();
5244 secondWindowInPrimary->consumeMotionDown();
5245
5246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005247 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005248 ADISPLAY_ID_DEFAULT, {150, 50}))
5249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5250 firstWindowInPrimary->assertNoEvents();
5251 secondWindowInPrimary->consumeMotionMove();
5252
5253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005254 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005255 {150, 50}))
5256 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5257 firstWindowInPrimary->assertNoEvents();
5258 secondWindowInPrimary->consumeMotionUp();
5259}
5260
5261// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5262// 'transferTouch' api.
5263TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5264 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5265 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005266 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005267 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005268 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005269 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005270 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005271
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005272 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005273 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005274
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005275 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005276 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005277
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005278 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005279 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005280
5281 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005282 mDispatcher->onWindowInfosChanged(
5283 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5284 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5285 *secondWindowInPrimary->getInfo()},
5286 {},
5287 0,
5288 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005289
5290 // Touch on second display.
5291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005292 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5293 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5295
5296 // Window should receive motion event.
5297 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5298
5299 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005300 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005301
5302 // The first window gets cancel.
5303 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5304 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5305
5306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005307 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005308 SECOND_DISPLAY_ID, {150, 50}))
5309 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5310 firstWindowInPrimary->assertNoEvents();
5311 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5312
5313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005314 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5316 firstWindowInPrimary->assertNoEvents();
5317 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5318}
5319
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005320TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005322 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5323 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005324
Vishnu Nair47074b82020-08-14 11:54:47 -07005325 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005326 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005327 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005328
5329 window->consumeFocusEvent(true);
5330
Prabir Pradhan678438e2023-04-13 19:32:51 +00005331 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005332
5333 // Window should receive key down event.
5334 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005335
5336 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005337 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005338 mFakePolicy->assertUserActivityPoked();
5339}
5340
5341TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5343 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5344 "Fake Window", ADISPLAY_ID_DEFAULT);
5345
5346 window->setDisableUserActivity(true);
5347 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005349 setFocusedWindow(window);
5350
5351 window->consumeFocusEvent(true);
5352
5353 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5354
5355 // Window should receive key down event.
5356 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5357
5358 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005359 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005360 mFakePolicy->assertUserActivityNotPoked();
5361}
5362
5363TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5365 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5366 "Fake Window", ADISPLAY_ID_DEFAULT);
5367
5368 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005369 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005370 setFocusedWindow(window);
5371
5372 window->consumeFocusEvent(true);
5373
5374 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5375 mDispatcher->waitForIdle();
5376
5377 // System key is not passed down
5378 window->assertNoEvents();
5379
5380 // Should have poked user activity
5381 mFakePolicy->assertUserActivityPoked();
5382}
5383
5384TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5386 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5387 "Fake Window", ADISPLAY_ID_DEFAULT);
5388
5389 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005390 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005391 setFocusedWindow(window);
5392
5393 window->consumeFocusEvent(true);
5394
5395 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5396 mDispatcher->waitForIdle();
5397
5398 // System key is not passed down
5399 window->assertNoEvents();
5400
5401 // Should have poked user activity
5402 mFakePolicy->assertUserActivityPoked();
5403}
5404
5405TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5407 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5408 "Fake Window", ADISPLAY_ID_DEFAULT);
5409
5410 window->setDisableUserActivity(true);
5411 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005413 setFocusedWindow(window);
5414
5415 window->consumeFocusEvent(true);
5416
5417 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5418 mDispatcher->waitForIdle();
5419
5420 // System key is not passed down
5421 window->assertNoEvents();
5422
5423 // Should have poked user activity
5424 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005425}
5426
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005427TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5429 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5430 "Fake Window", ADISPLAY_ID_DEFAULT);
5431
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005432 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005433
5434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005435 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005436 ADISPLAY_ID_DEFAULT, {100, 100}))
5437 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5438
5439 window->consumeMotionEvent(
5440 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5441
5442 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005443 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005444 mFakePolicy->assertUserActivityPoked();
5445}
5446
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005447TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005449 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5450 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005451
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005452 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005453
Prabir Pradhan678438e2023-04-13 19:32:51 +00005454 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005455 mDispatcher->waitForIdle();
5456
5457 window->assertNoEvents();
5458}
5459
5460// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5461TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005463 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5464 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005465
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005466 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005467
5468 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005469 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005470 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005471 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5472 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005473
5474 // Window should receive only the motion event
5475 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5476 window->assertNoEvents(); // Key event or focus event will not be received
5477}
5478
arthurhungea3f4fc2020-12-21 23:18:53 +08005479TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5480 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5481
arthurhungea3f4fc2020-12-21 23:18:53 +08005482 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005483 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5484 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005485 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005486
arthurhungea3f4fc2020-12-21 23:18:53 +08005487 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005488 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5489 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005490 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005491
5492 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005493 mDispatcher->onWindowInfosChanged(
5494 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005495
5496 PointF pointInFirst = {300, 200};
5497 PointF pointInSecond = {300, 600};
5498
5499 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005500 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5501 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5502 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005503 // Only the first window should get the down event
5504 firstWindow->consumeMotionDown();
5505 secondWindow->assertNoEvents();
5506
5507 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005508 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5509 ADISPLAY_ID_DEFAULT,
5510 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005511 // The first window gets a move and the second a down
5512 firstWindow->consumeMotionMove();
5513 secondWindow->consumeMotionDown();
5514
5515 // Send pointer cancel to the second window
5516 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005517 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005518 {pointInFirst, pointInSecond});
5519 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005520 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005521 // The first window gets move and the second gets cancel.
5522 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5523 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5524
5525 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5527 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005528 // The first window gets up and the second gets nothing.
5529 firstWindow->consumeMotionUp();
5530 secondWindow->assertNoEvents();
5531}
5532
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005533TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5534 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5535
5536 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005537 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005538 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005539 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5540 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5541 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5542
Harry Cutts33476232023-01-30 19:57:29 +00005543 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005544 window->assertNoEvents();
5545 mDispatcher->waitForIdle();
5546}
5547
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005548using InputDispatcherMonitorTest = InputDispatcherTest;
5549
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005550/**
5551 * Two entities that receive touch: A window, and a global monitor.
5552 * The touch goes to the window, and then the window disappears.
5553 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5554 * for the monitor, as well.
5555 * 1. foregroundWindow
5556 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5557 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005558TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5560 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005561 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005562
Prabir Pradhanfb549072023-10-05 19:17:36 +00005563 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005564
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005565 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005567 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005568 {100, 200}))
5569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5570
5571 // Both the foreground window and the global monitor should receive the touch down
5572 window->consumeMotionDown();
5573 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5574
5575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005576 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005577 ADISPLAY_ID_DEFAULT, {110, 200}))
5578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5579
5580 window->consumeMotionMove();
5581 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5582
5583 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005584 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005585 window->consumeMotionCancel();
5586 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5587
5588 // If more events come in, there will be no more foreground window to send them to. This will
5589 // cause a cancel for the monitor, as well.
5590 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005591 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005592 ADISPLAY_ID_DEFAULT, {120, 200}))
5593 << "Injection should fail because the window was removed";
5594 window->assertNoEvents();
5595 // Global monitor now gets the cancel
5596 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5597}
5598
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005599TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005600 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005601 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5602 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005603 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005604
Prabir Pradhanfb549072023-10-05 19:17:36 +00005605 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005606
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005608 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005609 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005610 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005611 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005612}
5613
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005614TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005615 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005616
Chris Yea209fde2020-07-22 13:54:51 -07005617 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005618 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5619 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005620 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005621
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005623 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005625 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005626 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005627
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005628 // Pilfer pointers from the monitor.
5629 // This should not do anything and the window should continue to receive events.
5630 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005631
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005633 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005634 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005636
5637 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5638 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005639}
5640
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005641TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005643 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5644 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005645 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005646 window->setWindowOffset(20, 40);
5647 window->setWindowTransform(0, 1, -1, 0);
5648
Prabir Pradhanfb549072023-10-05 19:17:36 +00005649 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005650
5651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005652 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5654 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5655 MotionEvent* event = monitor.consumeMotion();
5656 // Even though window has transform, gesture monitor must not.
5657 ASSERT_EQ(ui::Transform(), event->getTransform());
5658}
5659
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005660TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005662 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005663
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005664 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005666 << "Injection should fail if there is a monitor, but no touchable window";
5667 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005668}
5669
chaviw81e2bb92019-12-18 15:03:51 -08005670TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005671 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005672 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5673 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005674
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005675 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005676
5677 NotifyMotionArgs motionArgs =
5678 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5679 ADISPLAY_ID_DEFAULT);
5680
Prabir Pradhan678438e2023-04-13 19:32:51 +00005681 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005682 // Window should receive motion down event.
5683 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5684
5685 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005686 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005687 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5688 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5689 motionArgs.pointerCoords[0].getX() - 10);
5690
Prabir Pradhan678438e2023-04-13 19:32:51 +00005691 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005692 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005693 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005694}
5695
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005696/**
5697 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5698 * the device default right away. In the test scenario, we check both the default value,
5699 * and the action of enabling / disabling.
5700 */
5701TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5704 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005705 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005706
5707 // Set focused application.
5708 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005709 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005710
5711 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005713 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005714 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005715
5716 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005717 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005719 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005720
5721 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005722 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005723 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005724 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005725 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005726 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005727 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005728 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005729
5730 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005731 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005732 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005733 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005734
5735 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005736 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005737 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005738 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005739 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005740 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005741 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005742 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005743
5744 window->assertNoEvents();
5745}
5746
Gang Wange9087892020-01-07 12:17:14 -05005747TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5750 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005751
5752 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005753 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005756 setFocusedWindow(window);
5757
Harry Cutts33476232023-01-30 19:57:29 +00005758 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005759
Prabir Pradhan678438e2023-04-13 19:32:51 +00005760 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5761 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005762
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005763 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005764 ASSERT_NE(event, nullptr);
5765
5766 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5767 ASSERT_NE(verified, nullptr);
5768 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5769
5770 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5771 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5772 ASSERT_EQ(keyArgs.source, verified->source);
5773 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5774
5775 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5776
5777 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005778 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005779 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005780 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5781 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5782 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5783 ASSERT_EQ(0, verifiedKey.repeatCount);
5784}
5785
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005786TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5789 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005790
5791 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5792
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005793 ui::Transform transform;
5794 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5795
5796 gui::DisplayInfo displayInfo;
5797 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5798 displayInfo.transform = transform;
5799
Patrick Williamsd828f302023-04-28 17:52:08 -05005800 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005801
Prabir Pradhan678438e2023-04-13 19:32:51 +00005802 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005803 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5804 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005805 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005806
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005807 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005808 ASSERT_NE(event, nullptr);
5809
5810 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5811 ASSERT_NE(verified, nullptr);
5812 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5813
5814 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5815 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5816 EXPECT_EQ(motionArgs.source, verified->source);
5817 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5818
5819 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5820
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005821 const vec2 rawXY =
5822 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5823 motionArgs.pointerCoords[0].getXYValue());
5824 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5825 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005826 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005827 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005828 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005829 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5830 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5831}
5832
chaviw09c8d2d2020-08-24 15:48:26 -07005833/**
5834 * Ensure that separate calls to sign the same data are generating the same key.
5835 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5836 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5837 * tests.
5838 */
5839TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5840 KeyEvent event = getTestKeyEvent();
5841 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5842
5843 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5844 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5845 ASSERT_EQ(hmac1, hmac2);
5846}
5847
5848/**
5849 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5850 */
5851TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5852 KeyEvent event = getTestKeyEvent();
5853 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5854 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5855
5856 verifiedEvent.deviceId += 1;
5857 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5858
5859 verifiedEvent.source += 1;
5860 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5861
5862 verifiedEvent.eventTimeNanos += 1;
5863 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5864
5865 verifiedEvent.displayId += 1;
5866 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5867
5868 verifiedEvent.action += 1;
5869 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5870
5871 verifiedEvent.downTimeNanos += 1;
5872 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5873
5874 verifiedEvent.flags += 1;
5875 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5876
5877 verifiedEvent.keyCode += 1;
5878 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5879
5880 verifiedEvent.scanCode += 1;
5881 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5882
5883 verifiedEvent.metaState += 1;
5884 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5885
5886 verifiedEvent.repeatCount += 1;
5887 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5888}
5889
Vishnu Nair958da932020-08-21 17:12:37 -07005890TEST_F(InputDispatcherTest, SetFocusedWindow) {
5891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5892 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005893 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005894 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005895 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005896 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5897
5898 // Top window is also focusable but is not granted focus.
5899 windowTop->setFocusable(true);
5900 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005901 mDispatcher->onWindowInfosChanged(
5902 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005903 setFocusedWindow(windowSecond);
5904
5905 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005907 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005908
5909 // Focused window should receive event.
5910 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5911 windowTop->assertNoEvents();
5912}
5913
5914TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5916 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005917 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005918 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5919
5920 window->setFocusable(true);
5921 // Release channel for window is no longer valid.
5922 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005923 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005924 setFocusedWindow(window);
5925
5926 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005927 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005928
5929 // window channel is invalid, so it should not receive any input event.
5930 window->assertNoEvents();
5931}
5932
5933TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5935 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005936 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005937 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005938 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5939
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005940 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005941 setFocusedWindow(window);
5942
5943 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005944 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005945
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005946 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005947 window->assertNoEvents();
5948}
5949
5950TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5952 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005953 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005954 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005955 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005956 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5957
5958 windowTop->setFocusable(true);
5959 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005960 mDispatcher->onWindowInfosChanged(
5961 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005962 setFocusedWindow(windowTop);
5963 windowTop->consumeFocusEvent(true);
5964
Chavi Weingarten847e8512023-03-29 00:26:09 +00005965 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005966 mDispatcher->onWindowInfosChanged(
5967 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005968 windowSecond->consumeFocusEvent(true);
5969 windowTop->consumeFocusEvent(false);
5970
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005972 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005973
5974 // Focused window should receive event.
5975 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5976}
5977
Chavi Weingarten847e8512023-03-29 00:26:09 +00005978TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005979 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5980 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005981 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005982 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005983 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005984 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5985
5986 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005987 windowSecond->setFocusable(false);
5988 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005989 mDispatcher->onWindowInfosChanged(
5990 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005991 setFocusedWindow(windowTop);
5992 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005993
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005995 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005996
5997 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005998 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005999 windowSecond->assertNoEvents();
6000}
6001
6002TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6004 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006005 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006006 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006007 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6008 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006009 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6010
6011 window->setFocusable(true);
6012 previousFocusedWindow->setFocusable(true);
6013 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006014 mDispatcher->onWindowInfosChanged(
6015 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006016 setFocusedWindow(previousFocusedWindow);
6017 previousFocusedWindow->consumeFocusEvent(true);
6018
6019 // Requesting focus on invisible window takes focus from currently focused window.
6020 setFocusedWindow(window);
6021 previousFocusedWindow->consumeFocusEvent(false);
6022
6023 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006025 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6026 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006027
6028 // Window does not get focus event or key down.
6029 window->assertNoEvents();
6030
6031 // Window becomes visible.
6032 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006033 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006034
6035 // Window receives focus event.
6036 window->consumeFocusEvent(true);
6037 // Focused window receives key down.
6038 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6039}
6040
Vishnu Nair599f1412021-06-21 10:39:58 -07006041TEST_F(InputDispatcherTest, DisplayRemoved) {
6042 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6043 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006044 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006045 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6046
6047 // window is granted focus.
6048 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006049 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006050 setFocusedWindow(window);
6051 window->consumeFocusEvent(true);
6052
6053 // When a display is removed window loses focus.
6054 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6055 window->consumeFocusEvent(false);
6056}
6057
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006058/**
6059 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6060 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6061 * of the 'slipperyEnterWindow'.
6062 *
6063 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6064 * a way so that the touched location is no longer covered by the top window.
6065 *
6066 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6067 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6068 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6069 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6070 * with ACTION_DOWN).
6071 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6072 * window moved itself away from the touched location and had Flag::SLIPPERY.
6073 *
6074 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6075 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6076 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6077 *
6078 * In this test, we ensure that the event received by the bottom window has
6079 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6080 */
6081TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006082 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006083 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006084
6085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6086 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6087
6088 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006089 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006090 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006091 // Make sure this one overlaps the bottom window
6092 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6093 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6094 // one. Windows with the same owner are not considered to be occluding each other.
6095 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6096
6097 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006098 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006099 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6100
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006101 mDispatcher->onWindowInfosChanged(
6102 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006103
6104 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006105 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6106 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6107 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006108 slipperyExitWindow->consumeMotionDown();
6109 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006110 mDispatcher->onWindowInfosChanged(
6111 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006112
Prabir Pradhan678438e2023-04-13 19:32:51 +00006113 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6114 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6115 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006116
6117 slipperyExitWindow->consumeMotionCancel();
6118
6119 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6120 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6121}
6122
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006123/**
6124 * Two windows, one on the left and another on the right. The left window is slippery. The right
6125 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6126 * touch moves from the left window into the right window, the gesture should continue to go to the
6127 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6128 * reproduces a crash.
6129 */
6130TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6131 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6132
6133 sp<FakeWindowHandle> leftSlipperyWindow =
6134 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6135 leftSlipperyWindow->setSlippery(true);
6136 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6137
6138 sp<FakeWindowHandle> rightDropTouchesWindow =
6139 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6140 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6141 rightDropTouchesWindow->setDropInput(true);
6142
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006143 mDispatcher->onWindowInfosChanged(
6144 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006145
6146 // Start touch in the left window
6147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6148 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6149 .build());
6150 leftSlipperyWindow->consumeMotionDown();
6151
6152 // And move it into the right window
6153 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6154 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6155 .build());
6156
6157 // Since the right window isn't eligible to receive input, touch does not slip.
6158 // The left window continues to receive the gesture.
6159 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6160 rightDropTouchesWindow->assertNoEvents();
6161}
6162
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006163/**
6164 * A single window is on screen first. Touch is injected into that window. Next, a second window
6165 * appears. Since the first window is slippery, touch will move from the first window to the second.
6166 */
6167TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6169 sp<FakeWindowHandle> originalWindow =
6170 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6171 originalWindow->setFrame(Rect(0, 0, 200, 200));
6172 originalWindow->setSlippery(true);
6173
6174 sp<FakeWindowHandle> appearingWindow =
6175 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6176 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6177
6178 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6179
6180 // Touch down on the original window
6181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6182 injectMotionEvent(*mDispatcher,
6183 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6184 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6185 .build()));
6186 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6187
6188 // Now, a new window appears. This could be, for example, a notification shade that appears
6189 // after user starts to drag down on the launcher window.
6190 mDispatcher->onWindowInfosChanged(
6191 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6193 injectMotionEvent(*mDispatcher,
6194 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6195 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6196 .build()));
6197 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6198 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6200 injectMotionEvent(*mDispatcher,
6201 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6202 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6203 .build()));
6204 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6205
6206 originalWindow->assertNoEvents();
6207 appearingWindow->assertNoEvents();
6208}
6209
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006210TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006211 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6213
6214 sp<FakeWindowHandle> leftWindow =
6215 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6216 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006217 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006218
6219 sp<FakeWindowHandle> rightSpy =
6220 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6221 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006222 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006223 rightSpy->setSpy(true);
6224 rightSpy->setTrustedOverlay(true);
6225
6226 sp<FakeWindowHandle> rightWindow =
6227 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6228 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006229 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006230
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006231 mDispatcher->onWindowInfosChanged(
6232 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006233
6234 // Touch in the left window
6235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6236 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6237 .build());
6238 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6239 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006240 ASSERT_NO_FATAL_FAILURE(
6241 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006242
6243 // Touch another finger over the right windows
6244 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6245 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6246 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6247 .build());
6248 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6249 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6250 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6251 mDispatcher->waitForIdle();
6252 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006253 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6254 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006255
6256 // Release finger over left window. The UP actions are not treated as device interaction.
6257 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6258 // is part of the UP action, we do not treat this as device interaction.
6259 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6260 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6261 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6262 .build());
6263 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6264 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6265 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6266 mDispatcher->waitForIdle();
6267 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6268
6269 // Move remaining finger
6270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6271 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6272 .build());
6273 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6274 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6275 mDispatcher->waitForIdle();
6276 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006277 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006278
6279 // Release all fingers
6280 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6281 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6282 .build());
6283 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6284 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6285 mDispatcher->waitForIdle();
6286 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6287}
6288
6289TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6290 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6291
6292 sp<FakeWindowHandle> window =
6293 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6294 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006295 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006296
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006297 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006298 setFocusedWindow(window);
6299 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6300
6301 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6302 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6303 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006304 ASSERT_NO_FATAL_FAILURE(
6305 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006306
6307 // The UP actions are not treated as device interaction.
6308 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6309 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6310 mDispatcher->waitForIdle();
6311 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6312}
6313
Garfield Tan1c7bc862020-01-28 13:24:04 -08006314class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6315protected:
6316 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6317 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6318
Chris Yea209fde2020-07-22 13:54:51 -07006319 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006320 sp<FakeWindowHandle> mWindow;
6321
6322 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006323 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006324 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006325 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006326 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006327 ASSERT_EQ(OK, mDispatcher->start());
6328
6329 setUpWindow();
6330 }
6331
6332 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006333 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006334 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006335
Vishnu Nair47074b82020-08-14 11:54:47 -07006336 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006337 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006338 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006339 mWindow->consumeFocusEvent(true);
6340 }
6341
Chris Ye2ad95392020-09-01 13:44:44 -07006342 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006343 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006344 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006345 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006346 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006347
6348 // Window should receive key down event.
6349 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6350 }
6351
6352 void expectKeyRepeatOnce(int32_t repeatCount) {
6353 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006354 mWindow->consumeKeyEvent(
6355 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006356 }
6357
Chris Ye2ad95392020-09-01 13:44:44 -07006358 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006359 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006360 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006361 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006362 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006363
6364 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006365 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006366 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006367 }
6368};
6369
6370TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006371 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006372 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6373 expectKeyRepeatOnce(repeatCount);
6374 }
6375}
6376
6377TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006378 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006379 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6380 expectKeyRepeatOnce(repeatCount);
6381 }
Harry Cutts33476232023-01-30 19:57:29 +00006382 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006383 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006384 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6385 expectKeyRepeatOnce(repeatCount);
6386 }
6387}
6388
6389TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006390 sendAndConsumeKeyDown(/*deviceId=*/1);
6391 expectKeyRepeatOnce(/*repeatCount=*/1);
6392 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006393 mWindow->assertNoEvents();
6394}
6395
6396TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006397 sendAndConsumeKeyDown(/*deviceId=*/1);
6398 expectKeyRepeatOnce(/*repeatCount=*/1);
6399 sendAndConsumeKeyDown(/*deviceId=*/2);
6400 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006401 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006402 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006403 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006404 expectKeyRepeatOnce(/*repeatCount=*/2);
6405 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006406 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006407 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006408 mWindow->assertNoEvents();
6409}
6410
6411TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006412 sendAndConsumeKeyDown(/*deviceId=*/1);
6413 expectKeyRepeatOnce(/*repeatCount=*/1);
6414 sendAndConsumeKeyDown(/*deviceId=*/2);
6415 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006416 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006417 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006418 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006419 mWindow->assertNoEvents();
6420}
6421
liushenxiang42232912021-05-21 20:24:09 +08006422TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6423 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006424 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006425 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006426 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6427 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6428 mWindow->assertNoEvents();
6429}
6430
Garfield Tan1c7bc862020-01-28 13:24:04 -08006431TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006432 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006433 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006434 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006435 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006436 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6437 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6438 IdGenerator::getSource(repeatEvent->getId()));
6439 }
6440}
6441
6442TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006443 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006444 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006445
6446 std::unordered_set<int32_t> idSet;
6447 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006448 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006449 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6450 int32_t id = repeatEvent->getId();
6451 EXPECT_EQ(idSet.end(), idSet.find(id));
6452 idSet.insert(id);
6453 }
6454}
6455
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006456/* Test InputDispatcher for MultiDisplay */
6457class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6458public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006459 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006460 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006461
Chris Yea209fde2020-07-22 13:54:51 -07006462 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006463 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006464 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006465
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006466 // Set focus window for primary display, but focused display would be second one.
6467 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006468 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006469 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6470
Vishnu Nair958da932020-08-21 17:12:37 -07006471 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006472 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006473
Chris Yea209fde2020-07-22 13:54:51 -07006474 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006475 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006476 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006477 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006478 // Set focus display to second one.
6479 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6480 // Set focus window for second display.
6481 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006482 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006483 mDispatcher->onWindowInfosChanged(
6484 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006485 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006486 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006487 }
6488
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006489 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006490 InputDispatcherTest::TearDown();
6491
Chris Yea209fde2020-07-22 13:54:51 -07006492 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006493 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006494 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006495 windowInSecondary.clear();
6496 }
6497
6498protected:
Chris Yea209fde2020-07-22 13:54:51 -07006499 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006500 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006501 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006502 sp<FakeWindowHandle> windowInSecondary;
6503};
6504
6505TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6506 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006508 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006509 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006510 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006511 windowInSecondary->assertNoEvents();
6512
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006513 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006515 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006517 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006518 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006519}
6520
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006521TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006522 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006524 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006525 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006526 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006527 windowInSecondary->assertNoEvents();
6528
6529 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006531 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006532 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006533 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006534
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006535 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006536 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006537
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006538 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006539 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006540 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006541
6542 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006543 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006544 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006545 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006546 windowInSecondary->assertNoEvents();
6547}
6548
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006549// Test per-display input monitors for motion event.
6550TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006551 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006552 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006553 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006554 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006555
6556 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006558 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006559 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006560 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006561 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006562 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006563 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006564
6565 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006567 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006569 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006570 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006571 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006572 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006573
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006574 // Lift up the touch from the second display
6575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006576 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006577 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6578 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6579 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6580
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006581 // Test inject a non-pointer motion event.
6582 // If specific a display, it will dispatch to the focused window of particular display,
6583 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006585 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006586 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006587 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006588 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006589 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006590 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006591}
6592
6593// Test per-display input monitors for key event.
6594TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006595 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006596 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006597 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006598 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006599 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006600
6601 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006603 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006604 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006605 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006606 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006607 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006608}
6609
Vishnu Nair958da932020-08-21 17:12:37 -07006610TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6611 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006612 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006613 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006614 mDispatcher->onWindowInfosChanged(
6615 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6616 *windowInSecondary->getInfo()},
6617 {},
6618 0,
6619 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006620 setFocusedWindow(secondWindowInPrimary);
6621 windowInPrimary->consumeFocusEvent(false);
6622 secondWindowInPrimary->consumeFocusEvent(true);
6623
6624 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6626 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006627 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006628 windowInPrimary->assertNoEvents();
6629 windowInSecondary->assertNoEvents();
6630 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6631}
6632
Arthur Hungdfd528e2021-12-08 13:23:04 +00006633TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6634 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006635 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006636 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006637 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006638
6639 // Test touch down on primary display.
6640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006641 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6643 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6644 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6645
6646 // Test touch down on second display.
6647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006648 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6650 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6651 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6652
6653 // Trigger cancel touch.
6654 mDispatcher->cancelCurrentTouch();
6655 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6656 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6657 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6658 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6659
6660 // Test inject a move motion event, no window/monitor should receive the event.
6661 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006662 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006663 ADISPLAY_ID_DEFAULT, {110, 200}))
6664 << "Inject motion event should return InputEventInjectionResult::FAILED";
6665 windowInPrimary->assertNoEvents();
6666 monitorInPrimary.assertNoEvents();
6667
6668 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006669 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006670 SECOND_DISPLAY_ID, {110, 200}))
6671 << "Inject motion event should return InputEventInjectionResult::FAILED";
6672 windowInSecondary->assertNoEvents();
6673 monitorInSecondary.assertNoEvents();
6674}
6675
Jackal Guof9696682018-10-05 12:23:23 +08006676class InputFilterTest : public InputDispatcherTest {
6677protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006678 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6679 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006680 NotifyMotionArgs motionArgs;
6681
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006682 motionArgs =
6683 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006684 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006685 motionArgs =
6686 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006687 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006688 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006689 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006690 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006691 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006692 } else {
6693 mFakePolicy->assertFilterInputEventWasNotCalled();
6694 }
6695 }
6696
6697 void testNotifyKey(bool expectToBeFiltered) {
6698 NotifyKeyArgs keyArgs;
6699
6700 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006701 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006702 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006703 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006704 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006705
6706 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006707 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006708 } else {
6709 mFakePolicy->assertFilterInputEventWasNotCalled();
6710 }
6711 }
6712};
6713
6714// Test InputFilter for MotionEvent
6715TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6716 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006717 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6718 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006719
6720 // Enable InputFilter
6721 mDispatcher->setInputFilterEnabled(true);
6722 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006723 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6724 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006725
6726 // Disable InputFilter
6727 mDispatcher->setInputFilterEnabled(false);
6728 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006729 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6730 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006731}
6732
6733// Test InputFilter for KeyEvent
6734TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6735 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006736 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006737
6738 // Enable InputFilter
6739 mDispatcher->setInputFilterEnabled(true);
6740 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006741 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006742
6743 // Disable InputFilter
6744 mDispatcher->setInputFilterEnabled(false);
6745 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006746 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006747}
6748
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006749// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6750// logical display coordinate space.
6751TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6752 ui::Transform firstDisplayTransform;
6753 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6754 ui::Transform secondDisplayTransform;
6755 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6756
6757 std::vector<gui::DisplayInfo> displayInfos(2);
6758 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6759 displayInfos[0].transform = firstDisplayTransform;
6760 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6761 displayInfos[1].transform = secondDisplayTransform;
6762
Patrick Williamsd828f302023-04-28 17:52:08 -05006763 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006764
6765 // Enable InputFilter
6766 mDispatcher->setInputFilterEnabled(true);
6767
6768 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006769 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6770 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006771}
6772
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006773class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6774protected:
6775 virtual void SetUp() override {
6776 InputDispatcherTest::SetUp();
6777
6778 /**
6779 * We don't need to enable input filter to test the injected event policy, but we enabled it
6780 * here to make the tests more realistic, since this policy only matters when inputfilter is
6781 * on.
6782 */
6783 mDispatcher->setInputFilterEnabled(true);
6784
6785 std::shared_ptr<InputApplicationHandle> application =
6786 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006787 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6788 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006789
6790 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6791 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006792 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006793 setFocusedWindow(mWindow);
6794 mWindow->consumeFocusEvent(true);
6795 }
6796
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006797 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6798 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006799 KeyEvent event;
6800
6801 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6802 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6803 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006804 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006805 const int32_t additionalPolicyFlags =
6806 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006808 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006809 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006810 policyFlags | additionalPolicyFlags));
6811
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006812 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006813 }
6814
6815 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6816 int32_t flags) {
6817 MotionEvent event;
6818 PointerProperties pointerProperties[1];
6819 PointerCoords pointerCoords[1];
6820 pointerProperties[0].clear();
6821 pointerProperties[0].id = 0;
6822 pointerCoords[0].clear();
6823 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6824 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6825
6826 ui::Transform identityTransform;
6827 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6828 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6829 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6830 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6831 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006832 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006833 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006834 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006835
6836 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006838 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006839 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006840 policyFlags | additionalPolicyFlags));
6841
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006842 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006843 }
6844
6845private:
6846 sp<FakeWindowHandle> mWindow;
6847};
6848
6849TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006850 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6851 // filter. Without it, the event will no different from a regularly injected event, and the
6852 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006853 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6854 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006855}
6856
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006857TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006858 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006859 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006860 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6861}
6862
6863TEST_F(InputFilterInjectionPolicyTest,
6864 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6865 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006866 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006867 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006868}
6869
6870TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006871 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6872 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006873}
6874
chaviwfd6d3512019-03-25 13:23:49 -07006875class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006876 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006877 InputDispatcherTest::SetUp();
6878
Chris Yea209fde2020-07-22 13:54:51 -07006879 std::shared_ptr<FakeApplicationHandle> application =
6880 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006881 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006882 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006883 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006884
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006885 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006886 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006887 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006888
6889 // Set focused application.
6890 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006891 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006892
6893 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006894 mDispatcher->onWindowInfosChanged(
6895 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006896 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006897 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006898 }
6899
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006900 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006901 InputDispatcherTest::TearDown();
6902
6903 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006904 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006905 }
6906
6907protected:
6908 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006909 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006910 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006911};
6912
6913// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6914// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6915// the onPointerDownOutsideFocus callback.
6916TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006918 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006919 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006921 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006922
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006923 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006924 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6925}
6926
6927// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6928// DOWN on the window that doesn't have focus. Ensure no window received the
6929// onPointerDownOutsideFocus callback.
6930TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006932 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6933 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006935 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006936
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006937 ASSERT_TRUE(mDispatcher->waitForIdle());
6938 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006939}
6940
6941// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6942// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6943TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006945 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006946 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006947 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006948
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006949 ASSERT_TRUE(mDispatcher->waitForIdle());
6950 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006951}
6952
6953// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6954// DOWN on the window that already has focus. Ensure no window received the
6955// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006956TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006958 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006959 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006961 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006962
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006963 ASSERT_TRUE(mDispatcher->waitForIdle());
6964 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006965}
6966
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006967// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6968// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6969TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6970 const MotionEvent event =
6971 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6972 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006973 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006974 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6975 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6978 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6979
6980 ASSERT_TRUE(mDispatcher->waitForIdle());
6981 mFakePolicy->assertOnPointerDownWasNotCalled();
6982 // Ensure that the unfocused window did not receive any FOCUS events.
6983 mUnfocusedWindow->assertNoEvents();
6984}
6985
chaviwaf87b3e2019-10-01 16:59:28 -07006986// These tests ensures we can send touch events to a single client when there are multiple input
6987// windows that point to the same client token.
6988class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6989 virtual void SetUp() override {
6990 InputDispatcherTest::SetUp();
6991
Chris Yea209fde2020-07-22 13:54:51 -07006992 std::shared_ptr<FakeApplicationHandle> application =
6993 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006994 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6995 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006996 mWindow1->setFrame(Rect(0, 0, 100, 100));
6997
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006998 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6999 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007000 mWindow2->setFrame(Rect(100, 100, 200, 200));
7001
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007002 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007003 }
7004
7005protected:
7006 sp<FakeWindowHandle> mWindow1;
7007 sp<FakeWindowHandle> mWindow2;
7008
7009 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007010 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007011 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7012 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007013 }
7014
7015 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7016 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007017 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007018 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07007019
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007020 ASSERT_NE(nullptr, motionEvent)
7021 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07007022
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07007023 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007024 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007025
7026 for (size_t i = 0; i < points.size(); i++) {
7027 float expectedX = points[i].x;
7028 float expectedY = points[i].y;
7029
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007030 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007031 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007032 << ", got " << motionEvent->getX(i);
7033 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007034 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007035 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007036 }
7037 }
chaviw9eaa22c2020-07-01 16:21:27 -07007038
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007039 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007040 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007041 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7042 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007043
7044 // Always consume from window1 since it's the window that has the InputReceiver
7045 consumeMotionEvent(mWindow1, action, expectedPoints);
7046 }
chaviwaf87b3e2019-10-01 16:59:28 -07007047};
7048
7049TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7050 // Touch Window 1
7051 PointF touchedPoint = {10, 10};
7052 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007053 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007054
7055 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007056 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007057
7058 // Touch Window 2
7059 touchedPoint = {150, 150};
7060 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007061 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007062}
7063
chaviw9eaa22c2020-07-01 16:21:27 -07007064TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7065 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007066 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007067 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007068
7069 // Touch Window 1
7070 PointF touchedPoint = {10, 10};
7071 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007072 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007073 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007074 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007075
7076 // Touch Window 2
7077 touchedPoint = {150, 150};
7078 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007079 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7080 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007081
chaviw9eaa22c2020-07-01 16:21:27 -07007082 // Update the transform so rotation is set
7083 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007084 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007085 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7086 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007087}
7088
chaviw9eaa22c2020-07-01 16:21:27 -07007089TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007090 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007091 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007092
7093 // Touch Window 1
7094 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7095 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007096 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007097
7098 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007099 touchedPoints.push_back(PointF{150, 150});
7100 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007101 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007102
chaviw9eaa22c2020-07-01 16:21:27 -07007103 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007104 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007105 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007106
chaviw9eaa22c2020-07-01 16:21:27 -07007107 // Update the transform so rotation is set for Window 2
7108 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007109 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007110 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007111 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007112}
7113
chaviw9eaa22c2020-07-01 16:21:27 -07007114TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007115 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007116 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007117
7118 // Touch Window 1
7119 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7120 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007121 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007122
7123 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007124 touchedPoints.push_back(PointF{150, 150});
7125 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007126
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007127 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007128
7129 // Move both windows
7130 touchedPoints = {{20, 20}, {175, 175}};
7131 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7132 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7133
chaviw9eaa22c2020-07-01 16:21:27 -07007134 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007135
chaviw9eaa22c2020-07-01 16:21:27 -07007136 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007137 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007138 expectedPoints.pop_back();
7139
7140 // Touch Window 2
7141 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007142 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007143 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007144 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007145
7146 // Move both windows
7147 touchedPoints = {{20, 20}, {175, 175}};
7148 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7149 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7150
7151 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007152}
7153
7154TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7155 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007156 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007157
7158 // Touch Window 1
7159 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7160 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007161 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007162
7163 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007164 touchedPoints.push_back(PointF{150, 150});
7165 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007166
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007167 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007168
7169 // Move both windows
7170 touchedPoints = {{20, 20}, {175, 175}};
7171 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7172 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7173
chaviw9eaa22c2020-07-01 16:21:27 -07007174 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007175}
7176
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007177/**
7178 * When one of the windows is slippery, the touch should not slip into the other window with the
7179 * same input channel.
7180 */
7181TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7182 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007183 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007184
7185 // Touch down in window 1
7186 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7187 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7188 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7189
7190 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7191 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7192 // getting generated.
7193 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7194 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7195
7196 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7197}
7198
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007199/**
7200 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7201 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7202 * that the pointer is hovering over may have a different transform.
7203 */
7204TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007205 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007206
7207 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7209 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7210 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007211 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7212 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007213 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7215 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7216 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007217 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7218 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7219 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7220}
7221
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007222class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7223 virtual void SetUp() override {
7224 InputDispatcherTest::SetUp();
7225
Chris Yea209fde2020-07-22 13:54:51 -07007226 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007227 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007228 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7229 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007230 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007231 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007232 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007233
7234 // Set focused application.
7235 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7236
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007237 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007238 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007239 mWindow->consumeFocusEvent(true);
7240 }
7241
7242 virtual void TearDown() override {
7243 InputDispatcherTest::TearDown();
7244 mWindow.clear();
7245 }
7246
7247protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007248 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007249 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007250 sp<FakeWindowHandle> mWindow;
7251 static constexpr PointF WINDOW_LOCATION = {20, 20};
7252
7253 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007255 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007256 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007258 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007259 WINDOW_LOCATION));
7260 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007261
7262 sp<FakeWindowHandle> addSpyWindow() {
7263 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007264 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007265 spy->setTrustedOverlay(true);
7266 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007267 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007268 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007269 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007270 return spy;
7271 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007272};
7273
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007274// Send a tap and respond, which should not cause an ANR.
7275TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7276 tapOnWindow();
7277 mWindow->consumeMotionDown();
7278 mWindow->consumeMotionUp();
7279 ASSERT_TRUE(mDispatcher->waitForIdle());
7280 mFakePolicy->assertNotifyAnrWasNotCalled();
7281}
7282
7283// Send a regular key and respond, which should not cause an ANR.
7284TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007286 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7287 ASSERT_TRUE(mDispatcher->waitForIdle());
7288 mFakePolicy->assertNotifyAnrWasNotCalled();
7289}
7290
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007291TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7292 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007293 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007294 mWindow->consumeFocusEvent(false);
7295
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007296 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007297 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7298 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007299 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007301 // Key will not go to window because we have no focused window.
7302 // The 'no focused window' ANR timer should start instead.
7303
7304 // Now, the focused application goes away.
7305 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7306 // The key should get dropped and there should be no ANR.
7307
7308 ASSERT_TRUE(mDispatcher->waitForIdle());
7309 mFakePolicy->assertNotifyAnrWasNotCalled();
7310}
7311
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007312// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007313// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7314// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007315TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007317 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007318 WINDOW_LOCATION));
7319
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007320 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7321 ASSERT_TRUE(sequenceNum);
7322 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007323 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007324
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007325 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007326 mWindow->consumeMotionEvent(
7327 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007328 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007329 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007330}
7331
7332// Send a key to the app and have the app not respond right away.
7333TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7334 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007336 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7337 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007338 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007339 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007340 ASSERT_TRUE(mDispatcher->waitForIdle());
7341}
7342
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007343// We have a focused application, but no focused window
7344TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007345 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007346 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007347 mWindow->consumeFocusEvent(false);
7348
7349 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007351 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007352 WINDOW_LOCATION));
7353 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7354 mDispatcher->waitForIdle();
7355 mFakePolicy->assertNotifyAnrWasNotCalled();
7356
7357 // Once a focused event arrives, we get an ANR for this application
7358 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7359 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007360 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007361 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007362 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007363 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007364 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007365 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007366 ASSERT_TRUE(mDispatcher->waitForIdle());
7367}
7368
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007369/**
7370 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7371 * there will not be an ANR.
7372 */
7373TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7374 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007375 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007376 mWindow->consumeFocusEvent(false);
7377
7378 KeyEvent event;
7379 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7380 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7381
7382 // Define a valid key down event that is stale (too old).
7383 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007384 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007385 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007386
7387 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7388
7389 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007390 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007391 InputEventInjectionSync::WAIT_FOR_RESULT,
7392 INJECT_EVENT_TIMEOUT, policyFlags);
7393 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7394 << "Injection should fail because the event is stale";
7395
7396 ASSERT_TRUE(mDispatcher->waitForIdle());
7397 mFakePolicy->assertNotifyAnrWasNotCalled();
7398 mWindow->assertNoEvents();
7399}
7400
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007401// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007402// Make sure that we don't notify policy twice about the same ANR.
7403TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007404 const std::chrono::duration appTimeout = 400ms;
7405 mApplication->setDispatchingTimeout(appTimeout);
7406 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7407
Vishnu Nair47074b82020-08-14 11:54:47 -07007408 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007409 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007410 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007411
7412 // Once a focused event arrives, we get an ANR for this application
7413 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7414 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007415 const std::chrono::duration eventInjectionTimeout = 100ms;
7416 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007417 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007418 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007419 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7420 /*allowKeyRepeat=*/false);
7421 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7422 << "result=" << ftl::enum_string(result);
7423 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7424 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7425 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7426 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007427
Vishnu Naire4df8752022-09-08 09:17:55 -07007428 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007429 // ANR should not be raised again. It is up to policy to do that if it desires.
7430 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007431
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007432 // If we now get a focused window, the ANR should stop, but the policy handles that via
7433 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434 ASSERT_TRUE(mDispatcher->waitForIdle());
7435}
7436
7437// We have a focused application, but no focused window
7438TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007439 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007440 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007441 mWindow->consumeFocusEvent(false);
7442
7443 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007444 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007445
Vishnu Naire4df8752022-09-08 09:17:55 -07007446 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7447 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007448
7449 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007450 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007451 ASSERT_TRUE(mDispatcher->waitForIdle());
7452 mWindow->assertNoEvents();
7453}
7454
7455/**
7456 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7457 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7458 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7459 * the ANR mechanism should still work.
7460 *
7461 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7462 * DOWN event, while not responding on the second one.
7463 */
7464TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7465 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007466 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007467 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7468 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7469 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007470 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007471
7472 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007473 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007474 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7475 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7476 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007477 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007478
7479 // We have now sent down and up. Let's consume first event and then ANR on the second.
7480 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7481 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007482 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007483}
7484
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007485// A spy window can receive an ANR
7486TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7487 sp<FakeWindowHandle> spy = addSpyWindow();
7488
7489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007490 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007491 WINDOW_LOCATION));
7492 mWindow->consumeMotionDown();
7493
7494 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7495 ASSERT_TRUE(sequenceNum);
7496 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007497 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007498
7499 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007500 spy->consumeMotionEvent(
7501 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007502 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007503 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007504}
7505
7506// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007507// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007508TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7509 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007510
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007512 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007513 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007515
7516 // Stuck on the ACTION_UP
7517 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007518 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007519
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007520 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007521 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007522 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7523 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007524
7525 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7526 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007527 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007528 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007529 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007530}
7531
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007532// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007533// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007534TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7535 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007536
7537 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007538 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7539 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007540
7541 mWindow->consumeMotionDown();
7542 // Stuck on the ACTION_UP
7543 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007544 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007545
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007546 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007547 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007548 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7549 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007550
7551 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7552 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007553 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007554 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007555 spy->assertNoEvents();
7556}
7557
7558TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007559 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007560
Prabir Pradhanfb549072023-10-05 19:17:36 +00007561 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007562
7563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007564 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007565 WINDOW_LOCATION));
7566
7567 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7568 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7569 ASSERT_TRUE(consumeSeq);
7570
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007571 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7572 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007573
7574 monitor.finishEvent(*consumeSeq);
7575 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7576
7577 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007578 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007579}
7580
7581// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7582// process events, you don't get an anr. When the window later becomes unresponsive again, you
7583// get an ANR again.
7584// 1. tap -> block on ACTION_UP -> receive ANR
7585// 2. consume all pending events (= queue becomes healthy again)
7586// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7587TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7588 tapOnWindow();
7589
7590 mWindow->consumeMotionDown();
7591 // Block on ACTION_UP
7592 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007593 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007594 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7595 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007596 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007597 mWindow->assertNoEvents();
7598
7599 tapOnWindow();
7600 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007601 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007602 mWindow->consumeMotionUp();
7603
7604 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007605 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007606 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007607 mWindow->assertNoEvents();
7608}
7609
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007610// If a connection remains unresponsive for a while, make sure policy is only notified once about
7611// it.
7612TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007614 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007615 WINDOW_LOCATION));
7616
7617 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007618 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007619 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007620 // 'notifyConnectionUnresponsive' should only be called once per connection
7621 mFakePolicy->assertNotifyAnrWasNotCalled();
7622 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007623 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007624 mWindow->consumeMotionEvent(
7625 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007626 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007627 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007628 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007629 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007630}
7631
7632/**
7633 * If a window is processing a motion event, and then a key event comes in, the key event should
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007634 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007635 *
7636 * Warning!!!
7637 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7638 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007639 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007640 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7641 *
7642 * If that value changes, this test should also change.
7643 */
7644TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7645 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007646 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007647
7648 tapOnWindow();
7649 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7650 ASSERT_TRUE(downSequenceNum);
7651 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7652 ASSERT_TRUE(upSequenceNum);
7653 // Don't finish the events yet, and send a key
7654 // Injection will "succeed" because we will eventually give up and send the key to the focused
7655 // window even if motions are still being processed. But because the injection timeout is short,
7656 // we will receive INJECTION_TIMED_OUT as the result.
7657
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007658 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007659 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7660 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007661 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007662 // Key will not be sent to the window, yet, because the window is still processing events
7663 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007664 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7665 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7666 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7667 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007668
7669 std::this_thread::sleep_for(500ms);
7670 // if we wait long enough though, dispatcher will give up, and still send the key
7671 // to the focused window, even though we have not yet finished the motion event
7672 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7673 mWindow->finishEvent(*downSequenceNum);
7674 mWindow->finishEvent(*upSequenceNum);
7675}
7676
7677/**
7678 * If a window is processing a motion event, and then a key event comes in, the key event should
7679 * not go to the focused window until the motion is processed.
7680 * If then a new motion comes in, then the pending key event should be going to the currently
7681 * focused window right away.
7682 */
7683TEST_F(InputDispatcherSingleWindowAnr,
7684 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7685 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007686 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007687
7688 tapOnWindow();
7689 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7690 ASSERT_TRUE(downSequenceNum);
7691 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7692 ASSERT_TRUE(upSequenceNum);
7693 // Don't finish the events yet, and send a key
7694 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007696 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7697 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007698 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007699 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7700 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7701 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7702 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007703
7704 // Now tap down again. It should cause the pending key to go to the focused window right away.
7705 tapOnWindow();
7706 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7707 // the other events yet. We can finish events in any order.
7708 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7709 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7710 mWindow->consumeMotionDown();
7711 mWindow->consumeMotionUp();
7712 mWindow->assertNoEvents();
7713}
7714
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007715/**
7716 * Send an event to the app and have the app not respond right away.
7717 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7718 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7719 * At some point, the window becomes responsive again.
7720 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7721 */
7722TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7723 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7724 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7725 .build());
7726
7727 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7728 ASSERT_TRUE(sequenceNum);
7729 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7730 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7731
7732 mWindow->finishEvent(*sequenceNum);
7733 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7734 ASSERT_TRUE(mDispatcher->waitForIdle());
7735 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7736
7737 // Now that the window is responsive, let's continue the gesture.
7738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7739 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7740 .build());
7741
7742 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7743 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7744 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7745 .build());
7746
7747 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7748 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7749 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7750 .build());
7751 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7752 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7753 .build());
7754 // We already canceled this pointer, so the window shouldn't get any new events.
7755 mWindow->assertNoEvents();
7756
7757 // Start another one.
7758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7759 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7760 .build());
7761 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7762}
7763
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007764class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7765 virtual void SetUp() override {
7766 InputDispatcherTest::SetUp();
7767
Chris Yea209fde2020-07-22 13:54:51 -07007768 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007769 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007770 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7771 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007772 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007773 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007774 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007775
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007776 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7777 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007778 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007779 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007780
7781 // Set focused application.
7782 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007783 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784
7785 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007786 mDispatcher->onWindowInfosChanged(
7787 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007788 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007789 mFocusedWindow->consumeFocusEvent(true);
7790 }
7791
7792 virtual void TearDown() override {
7793 InputDispatcherTest::TearDown();
7794
7795 mUnfocusedWindow.clear();
7796 mFocusedWindow.clear();
7797 }
7798
7799protected:
Chris Yea209fde2020-07-22 13:54:51 -07007800 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007801 sp<FakeWindowHandle> mUnfocusedWindow;
7802 sp<FakeWindowHandle> mFocusedWindow;
7803 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7804 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7805 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7806
7807 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7808
7809 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7810
7811private:
7812 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007814 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007815 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007817 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007818 location));
7819 }
7820};
7821
7822// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7823// should be ANR'd first.
7824TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007826 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007827 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007829 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007830 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007831 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007832 // We consumed all events, so no ANR
7833 ASSERT_TRUE(mDispatcher->waitForIdle());
7834 mFakePolicy->assertNotifyAnrWasNotCalled();
7835
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007838 FOCUSED_WINDOW_LOCATION));
7839 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7840 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007841
7842 const std::chrono::duration timeout =
7843 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007844 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007845 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7846 // sequence to make it consistent
7847 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007848 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007849 mFocusedWindow->consumeMotionDown();
7850 // This cancel is generated because the connection was unresponsive
7851 mFocusedWindow->consumeMotionCancel();
7852 mFocusedWindow->assertNoEvents();
7853 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007854 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007855 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7856 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007857 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007858}
7859
7860// If we have 2 windows with identical timeouts that are both unresponsive,
7861// it doesn't matter which order they should have ANR.
7862// But we should receive ANR for both.
7863TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7864 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007865 mUnfocusedWindow->setDispatchingTimeout(
7866 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007867 mDispatcher->onWindowInfosChanged(
7868 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007869
7870 tapOnFocusedWindow();
7871 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007872 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007873 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7874 mFocusedWindow->getDispatchingTimeout(
7875 DISPATCHING_TIMEOUT)),
7876 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7877
7878 ASSERT_THAT(anrConnectionTokens,
7879 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7880 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007881
7882 ASSERT_TRUE(mDispatcher->waitForIdle());
7883 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007884
7885 mFocusedWindow->consumeMotionDown();
7886 mFocusedWindow->consumeMotionUp();
7887 mUnfocusedWindow->consumeMotionOutside();
7888
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007889 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7890 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007891
7892 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007893 ASSERT_THAT(responsiveTokens,
7894 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7895 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007896 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007897}
7898
7899// If a window is already not responding, the second tap on the same window should be ignored.
7900// We should also log an error to account for the dropped event (not tested here).
7901// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7902TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7903 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007904 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007905 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007906 // Receive the events, but don't respond
7907 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7908 ASSERT_TRUE(downEventSequenceNum);
7909 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7910 ASSERT_TRUE(upEventSequenceNum);
7911 const std::chrono::duration timeout =
7912 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007913 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007914
7915 // Tap once again
7916 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007917 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007918 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007919 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007920 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007921 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007922 FOCUSED_WINDOW_LOCATION));
7923 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7924 // valid touch target
7925 mUnfocusedWindow->assertNoEvents();
7926
7927 // Consume the first tap
7928 mFocusedWindow->finishEvent(*downEventSequenceNum);
7929 mFocusedWindow->finishEvent(*upEventSequenceNum);
7930 ASSERT_TRUE(mDispatcher->waitForIdle());
7931 // The second tap did not go to the focused window
7932 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007933 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007934 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7935 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936 mFakePolicy->assertNotifyAnrWasNotCalled();
7937}
7938
7939// If you tap outside of all windows, there will not be ANR
7940TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007941 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007942 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007943 LOCATION_OUTSIDE_ALL_WINDOWS));
7944 ASSERT_TRUE(mDispatcher->waitForIdle());
7945 mFakePolicy->assertNotifyAnrWasNotCalled();
7946}
7947
7948// Since the focused window is paused, tapping on it should not produce any events
7949TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7950 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007951 mDispatcher->onWindowInfosChanged(
7952 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007953
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007954 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007955 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007956 FOCUSED_WINDOW_LOCATION));
7957
7958 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7959 ASSERT_TRUE(mDispatcher->waitForIdle());
7960 // Should not ANR because the window is paused, and touches shouldn't go to it
7961 mFakePolicy->assertNotifyAnrWasNotCalled();
7962
7963 mFocusedWindow->assertNoEvents();
7964 mUnfocusedWindow->assertNoEvents();
7965}
7966
7967/**
7968 * If a window is processing a motion event, and then a key event comes in, the key event should
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007969 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007970 * If a different window becomes focused at this time, the key should go to that window instead.
7971 *
7972 * Warning!!!
7973 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7974 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007975 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007976 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7977 *
7978 * If that value changes, this test should also change.
7979 */
7980TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7981 // Set a long ANR timeout to prevent it from triggering
7982 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007983 mDispatcher->onWindowInfosChanged(
7984 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007985
7986 tapOnUnfocusedWindow();
7987 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7988 ASSERT_TRUE(downSequenceNum);
7989 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7990 ASSERT_TRUE(upSequenceNum);
7991 // Don't finish the events yet, and send a key
7992 // Injection will succeed because we will eventually give up and send the key to the focused
7993 // window even if motions are still being processed.
7994
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007995 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007996 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7997 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007999 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008000 // and the key remains pending, waiting for the touch events to be processed.
8001 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8002 // under the hood.
8003 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8004 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008005
8006 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008007 mFocusedWindow->setFocusable(false);
8008 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008009 mDispatcher->onWindowInfosChanged(
8010 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008011 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008012
8013 // Focus events should precede the key events
8014 mUnfocusedWindow->consumeFocusEvent(true);
8015 mFocusedWindow->consumeFocusEvent(false);
8016
8017 // Finish the tap events, which should unblock dispatcher
8018 mUnfocusedWindow->finishEvent(*downSequenceNum);
8019 mUnfocusedWindow->finishEvent(*upSequenceNum);
8020
8021 // Now that all queues are cleared and no backlog in the connections, the key event
8022 // can finally go to the newly focused "mUnfocusedWindow".
8023 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8024 mFocusedWindow->assertNoEvents();
8025 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008026 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008027}
8028
8029// When the touch stream is split across 2 windows, and one of them does not respond,
8030// then ANR should be raised and the touch should be canceled for the unresponsive window.
8031// The other window should not be affected by that.
8032TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8033 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008034 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8035 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8036 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008037 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00008038 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008039
8040 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008041 mDispatcher->notifyMotion(
8042 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8043 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008044
8045 const std::chrono::duration timeout =
8046 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008047 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008048
8049 mUnfocusedWindow->consumeMotionDown();
8050 mFocusedWindow->consumeMotionDown();
8051 // Focused window may or may not receive ACTION_MOVE
8052 // But it should definitely receive ACTION_CANCEL due to the ANR
8053 InputEvent* event;
8054 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8055 ASSERT_TRUE(moveOrCancelSequenceNum);
8056 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8057 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008058 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008059 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8060 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8061 mFocusedWindow->consumeMotionCancel();
8062 } else {
8063 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8064 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008065 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008066 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8067 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008068
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008069 mUnfocusedWindow->assertNoEvents();
8070 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008071 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008072}
8073
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008074/**
8075 * If we have no focused window, and a key comes in, we start the ANR timer.
8076 * The focused application should add a focused window before the timer runs out to prevent ANR.
8077 *
8078 * If the user touches another application during this time, the key should be dropped.
8079 * Next, if a new focused window comes in, without toggling the focused application,
8080 * then no ANR should occur.
8081 *
8082 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8083 * but in some cases the policy may not update the focused application.
8084 */
8085TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8086 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8087 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008088 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008089 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8090 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8091 mFocusedWindow->setFocusable(false);
8092
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008093 mDispatcher->onWindowInfosChanged(
8094 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008095 mFocusedWindow->consumeFocusEvent(false);
8096
8097 // Send a key. The ANR timer should start because there is no focused window.
8098 // 'focusedApplication' will get blamed if this timer completes.
8099 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008100 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008101 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8102 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008103 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008105
8106 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8107 // then the injected touches won't cause the focused event to get dropped.
8108 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8109 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8110 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8111 // For this test, it means that the key would get delivered to the window once it becomes
8112 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008113 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008114
8115 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008116 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8117 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8118 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008119
8120 // We do not consume the motion right away, because that would require dispatcher to first
8121 // process (== drop) the key event, and by that time, ANR will be raised.
8122 // Set the focused window first.
8123 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008124 mDispatcher->onWindowInfosChanged(
8125 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008126 setFocusedWindow(mFocusedWindow);
8127 mFocusedWindow->consumeFocusEvent(true);
8128 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8129 // to another application. This could be a bug / behaviour in the policy.
8130
8131 mUnfocusedWindow->consumeMotionDown();
8132
8133 ASSERT_TRUE(mDispatcher->waitForIdle());
8134 // Should not ANR because we actually have a focused window. It was just added too slowly.
8135 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8136}
8137
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008138// These tests ensure we cannot send touch events to a window that's positioned behind a window
8139// that has feature NO_INPUT_CHANNEL.
8140// Layout:
8141// Top (closest to user)
8142// mNoInputWindow (above all windows)
8143// mBottomWindow
8144// Bottom (furthest from user)
8145class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8146 virtual void SetUp() override {
8147 InputDispatcherTest::SetUp();
8148
8149 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008150 mNoInputWindow =
8151 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8152 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008153 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008154 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008155 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8156 // It's perfectly valid for this window to not have an associated input channel
8157
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008158 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8159 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008160 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8161
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008162 mDispatcher->onWindowInfosChanged(
8163 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008164 }
8165
8166protected:
8167 std::shared_ptr<FakeApplicationHandle> mApplication;
8168 sp<FakeWindowHandle> mNoInputWindow;
8169 sp<FakeWindowHandle> mBottomWindow;
8170};
8171
8172TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8173 PointF touchedPoint = {10, 10};
8174
Prabir Pradhan678438e2023-04-13 19:32:51 +00008175 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8176 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8177 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008178
8179 mNoInputWindow->assertNoEvents();
8180 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8181 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8182 // and therefore should prevent mBottomWindow from receiving touches
8183 mBottomWindow->assertNoEvents();
8184}
8185
8186/**
8187 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8188 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8189 */
8190TEST_F(InputDispatcherMultiWindowOcclusionTests,
8191 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008192 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8193 "Window with input channel and NO_INPUT_CHANNEL",
8194 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008195
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008196 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008197 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008198 mDispatcher->onWindowInfosChanged(
8199 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008200
8201 PointF touchedPoint = {10, 10};
8202
Prabir Pradhan678438e2023-04-13 19:32:51 +00008203 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8204 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8205 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008206
8207 mNoInputWindow->assertNoEvents();
8208 mBottomWindow->assertNoEvents();
8209}
8210
Vishnu Nair958da932020-08-21 17:12:37 -07008211class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8212protected:
8213 std::shared_ptr<FakeApplicationHandle> mApp;
8214 sp<FakeWindowHandle> mWindow;
8215 sp<FakeWindowHandle> mMirror;
8216
8217 virtual void SetUp() override {
8218 InputDispatcherTest::SetUp();
8219 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008220 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8221 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8222 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008223 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8224 mWindow->setFocusable(true);
8225 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008226 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008227 }
8228};
8229
8230TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8231 // Request focus on a mirrored window
8232 setFocusedWindow(mMirror);
8233
8234 // window gets focused
8235 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008237 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008238 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8239}
8240
8241// A focused & mirrored window remains focused only if the window and its mirror are both
8242// focusable.
8243TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8244 setFocusedWindow(mMirror);
8245
8246 // window gets focused
8247 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008249 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008250 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008252 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008253 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8254
8255 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008256 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008257
8258 // window loses focus since one of the windows associated with the token in not focusable
8259 mWindow->consumeFocusEvent(false);
8260
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008261 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008262 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008263 mWindow->assertNoEvents();
8264}
8265
8266// A focused & mirrored window remains focused until the window and its mirror both become
8267// invisible.
8268TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8269 setFocusedWindow(mMirror);
8270
8271 // window gets focused
8272 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008274 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008275 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008277 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008278 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8279
8280 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008281 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008282
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008284 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008285 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008287 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008288 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8289
8290 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008291 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008292
8293 // window loses focus only after all windows associated with the token become invisible.
8294 mWindow->consumeFocusEvent(false);
8295
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008296 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008297 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008298 mWindow->assertNoEvents();
8299}
8300
8301// A focused & mirrored window remains focused until both windows are removed.
8302TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8303 setFocusedWindow(mMirror);
8304
8305 // window gets focused
8306 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008308 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008309 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008311 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008312 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8313
8314 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008315 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008316
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008318 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008319 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008321 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008322 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8323
8324 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008325 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008326 mWindow->consumeFocusEvent(false);
8327
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008328 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008329 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008330 mWindow->assertNoEvents();
8331}
8332
8333// Focus request can be pending until one window becomes visible.
8334TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8335 // Request focus on an invisible mirror.
8336 mWindow->setVisible(false);
8337 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008338 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008339 setFocusedWindow(mMirror);
8340
8341 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008343 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8344 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008345
8346 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008347 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008348
8349 // window gets focused
8350 mWindow->consumeFocusEvent(true);
8351 // window gets the pending key event
8352 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8353}
Prabir Pradhan99987712020-11-10 18:43:05 -08008354
8355class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8356protected:
8357 std::shared_ptr<FakeApplicationHandle> mApp;
8358 sp<FakeWindowHandle> mWindow;
8359 sp<FakeWindowHandle> mSecondWindow;
8360
8361 void SetUp() override {
8362 InputDispatcherTest::SetUp();
8363 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008364 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008365 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008366 mSecondWindow =
8367 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008368 mSecondWindow->setFocusable(true);
8369
8370 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008371 mDispatcher->onWindowInfosChanged(
8372 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008373
8374 setFocusedWindow(mWindow);
8375 mWindow->consumeFocusEvent(true);
8376 }
8377
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008378 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008379 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008380 }
8381
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008382 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8383 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008384 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008385 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8386 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008387 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008388 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008389 }
8390};
8391
8392TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8393 // Ensure that capture cannot be obtained for unfocused windows.
8394 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8395 mFakePolicy->assertSetPointerCaptureNotCalled();
8396 mSecondWindow->assertNoEvents();
8397
8398 // Ensure that capture can be enabled from the focus window.
8399 requestAndVerifyPointerCapture(mWindow, true);
8400
8401 // Ensure that capture cannot be disabled from a window that does not have capture.
8402 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8403 mFakePolicy->assertSetPointerCaptureNotCalled();
8404
8405 // Ensure that capture can be disabled from the window with capture.
8406 requestAndVerifyPointerCapture(mWindow, false);
8407}
8408
8409TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008410 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008411
8412 setFocusedWindow(mSecondWindow);
8413
8414 // Ensure that the capture disabled event was sent first.
8415 mWindow->consumeCaptureEvent(false);
8416 mWindow->consumeFocusEvent(false);
8417 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008418 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008419
8420 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008421 notifyPointerCaptureChanged({});
8422 notifyPointerCaptureChanged(request);
8423 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008424 mWindow->assertNoEvents();
8425 mSecondWindow->assertNoEvents();
8426 mFakePolicy->assertSetPointerCaptureNotCalled();
8427}
8428
8429TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008430 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008431
8432 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008433 notifyPointerCaptureChanged({});
8434 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008435
8436 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008437 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008438 mWindow->consumeCaptureEvent(false);
8439 mWindow->assertNoEvents();
8440}
8441
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008442TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8443 requestAndVerifyPointerCapture(mWindow, true);
8444
8445 // The first window loses focus.
8446 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008447 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008448 mWindow->consumeCaptureEvent(false);
8449
8450 // Request Pointer Capture from the second window before the notification from InputReader
8451 // arrives.
8452 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008453 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008454
8455 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008456 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008457
8458 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008459 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008460
8461 mSecondWindow->consumeFocusEvent(true);
8462 mSecondWindow->consumeCaptureEvent(true);
8463}
8464
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008465TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8466 // App repeatedly enables and disables capture.
8467 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8468 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8469 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8470 mFakePolicy->assertSetPointerCaptureCalled(false);
8471 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8472 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8473
8474 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8475 // first request is now stale, this should do nothing.
8476 notifyPointerCaptureChanged(firstRequest);
8477 mWindow->assertNoEvents();
8478
8479 // InputReader notifies that the second request was enabled.
8480 notifyPointerCaptureChanged(secondRequest);
8481 mWindow->consumeCaptureEvent(true);
8482}
8483
Prabir Pradhan7092e262022-05-03 16:51:09 +00008484TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8485 requestAndVerifyPointerCapture(mWindow, true);
8486
8487 // App toggles pointer capture off and on.
8488 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8489 mFakePolicy->assertSetPointerCaptureCalled(false);
8490
8491 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8492 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8493
8494 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8495 // preceding "disable" request.
8496 notifyPointerCaptureChanged(enableRequest);
8497
8498 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8499 // any notifications.
8500 mWindow->assertNoEvents();
8501}
8502
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008503/**
8504 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8505 * mouse movements don't affect the previous mouse hovering state.
8506 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8507 * HOVER_MOVE events).
8508 */
8509TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8510 // Mouse hover on the window
8511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8512 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8513 .build());
8514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8515 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8516 .build());
8517
8518 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8519 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8520
8521 // Start pointer capture
8522 requestAndVerifyPointerCapture(mWindow, true);
8523
8524 // Send some relative mouse movements and receive them in the window.
8525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8526 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8527 .build());
8528 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8529 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8530
8531 // Stop pointer capture
8532 requestAndVerifyPointerCapture(mWindow, false);
8533
8534 // Continue hovering on the window
8535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8536 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8537 .build());
8538 mWindow->consumeMotionEvent(
8539 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8540
8541 mWindow->assertNoEvents();
8542}
8543
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008544class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8545protected:
8546 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008547
8548 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8549 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8550
8551 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8552 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8553
8554 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8555 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8556 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8557 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8558 MAXIMUM_OBSCURING_OPACITY);
8559
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008560 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8561 static constexpr gui::Uid APP_B_UID{10002};
8562 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008563
8564 sp<FakeWindowHandle> mTouchWindow;
8565
8566 virtual void SetUp() override {
8567 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008568 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008569 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8570 }
8571
8572 virtual void TearDown() override {
8573 InputDispatcherTest::TearDown();
8574 mTouchWindow.clear();
8575 }
8576
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008577 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008578 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008579 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008580 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008581 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008582 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008583 return window;
8584 }
8585
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008586 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008587 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8588 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008589 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008590 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008591 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008592 return window;
8593 }
8594
8595 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008596 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8597 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8598 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008599 }
8600};
8601
8602TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008603 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008604 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008605 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008606
8607 touch();
8608
8609 mTouchWindow->assertNoEvents();
8610}
8611
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008612TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008613 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8614 const sp<FakeWindowHandle>& w =
8615 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008616 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008617
8618 touch();
8619
8620 mTouchWindow->assertNoEvents();
8621}
8622
8623TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008624 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8625 const sp<FakeWindowHandle>& w =
8626 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008627 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008628
8629 touch();
8630
8631 w->assertNoEvents();
8632}
8633
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008634TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008635 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008636 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008637
8638 touch();
8639
8640 mTouchWindow->consumeAnyMotionDown();
8641}
8642
8643TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008644 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008645 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008646 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008647 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008648
8649 touch({PointF{100, 100}});
8650
8651 mTouchWindow->consumeAnyMotionDown();
8652}
8653
8654TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008655 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008656 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008657 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008658
8659 touch();
8660
8661 mTouchWindow->consumeAnyMotionDown();
8662}
8663
8664TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8665 const sp<FakeWindowHandle>& w =
8666 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008667 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008668
8669 touch();
8670
8671 mTouchWindow->consumeAnyMotionDown();
8672}
8673
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008674TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8675 const sp<FakeWindowHandle>& w =
8676 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008677 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008678
8679 touch();
8680
8681 w->assertNoEvents();
8682}
8683
8684/**
8685 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8686 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8687 * window, the occluding window will still receive ACTION_OUTSIDE event.
8688 */
8689TEST_F(InputDispatcherUntrustedTouchesTest,
8690 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8691 const sp<FakeWindowHandle>& w =
8692 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008693 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008694 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008695
8696 touch();
8697
8698 w->consumeMotionOutside();
8699}
8700
8701TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8702 const sp<FakeWindowHandle>& w =
8703 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008704 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008705 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008706
8707 touch();
8708
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008709 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008710}
8711
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008712TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008713 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008714 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8715 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008716 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008717
8718 touch();
8719
8720 mTouchWindow->consumeAnyMotionDown();
8721}
8722
8723TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8724 const sp<FakeWindowHandle>& w =
8725 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8726 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008727 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008728
8729 touch();
8730
8731 mTouchWindow->consumeAnyMotionDown();
8732}
8733
8734TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008735 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008736 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8737 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008738 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008739
8740 touch();
8741
8742 mTouchWindow->assertNoEvents();
8743}
8744
8745TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8746 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8747 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008748 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8749 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008750 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008751 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8752 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008753 mDispatcher->onWindowInfosChanged(
8754 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008755
8756 touch();
8757
8758 mTouchWindow->assertNoEvents();
8759}
8760
8761TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8762 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8763 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008764 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8765 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008766 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008767 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8768 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008769 mDispatcher->onWindowInfosChanged(
8770 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008771
8772 touch();
8773
8774 mTouchWindow->consumeAnyMotionDown();
8775}
8776
8777TEST_F(InputDispatcherUntrustedTouchesTest,
8778 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8779 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008780 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8781 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008782 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008783 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8784 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008785 mDispatcher->onWindowInfosChanged(
8786 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008787
8788 touch();
8789
8790 mTouchWindow->consumeAnyMotionDown();
8791}
8792
8793TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8794 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008795 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8796 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008797 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008798 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8799 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008800 mDispatcher->onWindowInfosChanged(
8801 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008802
8803 touch();
8804
8805 mTouchWindow->assertNoEvents();
8806}
8807
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008808TEST_F(InputDispatcherUntrustedTouchesTest,
8809 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8810 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008811 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8812 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008813 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008814 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8815 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged(
8817 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008818
8819 touch();
8820
8821 mTouchWindow->assertNoEvents();
8822}
8823
8824TEST_F(InputDispatcherUntrustedTouchesTest,
8825 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8826 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008827 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8828 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008829 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008830 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8831 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008832 mDispatcher->onWindowInfosChanged(
8833 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008834
8835 touch();
8836
8837 mTouchWindow->consumeAnyMotionDown();
8838}
8839
8840TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8841 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008842 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8843 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008844 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008845
8846 touch();
8847
8848 mTouchWindow->consumeAnyMotionDown();
8849}
8850
8851TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8852 const sp<FakeWindowHandle>& w =
8853 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008854 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008855
8856 touch();
8857
8858 mTouchWindow->consumeAnyMotionDown();
8859}
8860
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008861TEST_F(InputDispatcherUntrustedTouchesTest,
8862 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8863 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8864 const sp<FakeWindowHandle>& w =
8865 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008866 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008867
8868 touch();
8869
8870 mTouchWindow->assertNoEvents();
8871}
8872
8873TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8874 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8875 const sp<FakeWindowHandle>& w =
8876 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008877 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008878
8879 touch();
8880
8881 mTouchWindow->consumeAnyMotionDown();
8882}
8883
8884TEST_F(InputDispatcherUntrustedTouchesTest,
8885 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8886 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8887 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008888 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8889 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008890 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008891
8892 touch();
8893
8894 mTouchWindow->consumeAnyMotionDown();
8895}
8896
8897TEST_F(InputDispatcherUntrustedTouchesTest,
8898 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8899 const sp<FakeWindowHandle>& w1 =
8900 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8901 OPACITY_BELOW_THRESHOLD);
8902 const sp<FakeWindowHandle>& w2 =
8903 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8904 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008905 mDispatcher->onWindowInfosChanged(
8906 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008907
8908 touch();
8909
8910 mTouchWindow->assertNoEvents();
8911}
8912
8913/**
8914 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8915 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8916 * (which alone would result in allowing touches) does not affect the blocking behavior.
8917 */
8918TEST_F(InputDispatcherUntrustedTouchesTest,
8919 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8920 const sp<FakeWindowHandle>& wB =
8921 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8922 OPACITY_BELOW_THRESHOLD);
8923 const sp<FakeWindowHandle>& wC =
8924 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8925 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008926 mDispatcher->onWindowInfosChanged(
8927 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008928
8929 touch();
8930
8931 mTouchWindow->assertNoEvents();
8932}
8933
8934/**
8935 * This test is testing that a window from a different UID but with same application token doesn't
8936 * block the touch. Apps can share the application token for close UI collaboration for example.
8937 */
8938TEST_F(InputDispatcherUntrustedTouchesTest,
8939 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8940 const sp<FakeWindowHandle>& w =
8941 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8942 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008943 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008944
8945 touch();
8946
8947 mTouchWindow->consumeAnyMotionDown();
8948}
8949
arthurhungb89ccb02020-12-30 16:19:01 +08008950class InputDispatcherDragTests : public InputDispatcherTest {
8951protected:
8952 std::shared_ptr<FakeApplicationHandle> mApp;
8953 sp<FakeWindowHandle> mWindow;
8954 sp<FakeWindowHandle> mSecondWindow;
8955 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008956 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008957 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8958 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008959
8960 void SetUp() override {
8961 InputDispatcherTest::SetUp();
8962 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008963 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008964 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008965
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008966 mSecondWindow =
8967 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008968 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008969
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008970 mSpyWindow =
8971 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008972 mSpyWindow->setSpy(true);
8973 mSpyWindow->setTrustedOverlay(true);
8974 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8975
arthurhungb89ccb02020-12-30 16:19:01 +08008976 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008977 mDispatcher->onWindowInfosChanged(
8978 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8979 {},
8980 0,
8981 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008982 }
8983
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008984 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8985 switch (fromSource) {
8986 case AINPUT_SOURCE_TOUCHSCREEN:
8987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008988 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008989 ADISPLAY_ID_DEFAULT, {50, 50}))
8990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8991 break;
8992 case AINPUT_SOURCE_STYLUS:
8993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008994 injectMotionEvent(*mDispatcher,
8995 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8996 AINPUT_SOURCE_STYLUS)
8997 .buttonState(
8998 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8999 .pointer(PointerBuilder(0, ToolType::STYLUS)
9000 .x(50)
9001 .y(50))
9002 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009003 break;
9004 case AINPUT_SOURCE_MOUSE:
9005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009006 injectMotionEvent(*mDispatcher,
9007 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9008 AINPUT_SOURCE_MOUSE)
9009 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9010 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9011 ToolType::MOUSE)
9012 .x(50)
9013 .y(50))
9014 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009015 break;
9016 default:
9017 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9018 }
arthurhungb89ccb02020-12-30 16:19:01 +08009019
9020 // Window should receive motion event.
9021 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009022 // Spy window should also receive motion event
9023 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009024 }
9025
9026 // Start performing drag, we will create a drag window and transfer touch to it.
9027 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9028 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009029 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009030 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009031 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009032 }
arthurhungb89ccb02020-12-30 16:19:01 +08009033
9034 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009035 mDragWindow =
9036 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009037 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009038 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9039 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9040 {},
9041 0,
9042 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009043
9044 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009045 bool transferred =
9046 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009047 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009048 if (transferred) {
9049 mWindow->consumeMotionCancel();
9050 mDragWindow->consumeMotionDown();
9051 }
9052 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009053 }
9054};
9055
9056TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009057 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009058
9059 // Move on window.
9060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009061 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009062 ADISPLAY_ID_DEFAULT, {50, 50}))
9063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9064 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9065 mWindow->consumeDragEvent(false, 50, 50);
9066 mSecondWindow->assertNoEvents();
9067
9068 // Move to another window.
9069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009070 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009071 ADISPLAY_ID_DEFAULT, {150, 50}))
9072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9073 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9074 mWindow->consumeDragEvent(true, 150, 50);
9075 mSecondWindow->consumeDragEvent(false, 50, 50);
9076
9077 // Move back to original window.
9078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009079 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009080 ADISPLAY_ID_DEFAULT, {50, 50}))
9081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9082 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9083 mWindow->consumeDragEvent(false, 50, 50);
9084 mSecondWindow->consumeDragEvent(true, -50, 50);
9085
9086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009087 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9088 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9090 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9091 mWindow->assertNoEvents();
9092 mSecondWindow->assertNoEvents();
9093}
9094
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009095TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009096 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009097
9098 // No cancel event after drag start
9099 mSpyWindow->assertNoEvents();
9100
9101 const MotionEvent secondFingerDownEvent =
9102 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9103 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009104 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9105 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009106 .build();
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009108 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009109 InputEventInjectionSync::WAIT_FOR_RESULT))
9110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9111
9112 // Receives cancel for first pointer after next pointer down
9113 mSpyWindow->consumeMotionCancel();
9114 mSpyWindow->consumeMotionDown();
9115
9116 mSpyWindow->assertNoEvents();
9117}
9118
arthurhungf452d0b2021-01-06 00:19:52 +08009119TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009120 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009121
9122 // Move on window.
9123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009124 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009125 ADISPLAY_ID_DEFAULT, {50, 50}))
9126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9127 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9128 mWindow->consumeDragEvent(false, 50, 50);
9129 mSecondWindow->assertNoEvents();
9130
9131 // Move to another window.
9132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009133 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009134 ADISPLAY_ID_DEFAULT, {150, 50}))
9135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9136 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9137 mWindow->consumeDragEvent(true, 150, 50);
9138 mSecondWindow->consumeDragEvent(false, 50, 50);
9139
9140 // drop to another window.
9141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009142 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009143 {150, 50}))
9144 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9145 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009146 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009147 mWindow->assertNoEvents();
9148 mSecondWindow->assertNoEvents();
9149}
9150
arthurhung6d4bed92021-03-17 11:59:33 +08009151TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009152 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009153
9154 // Move on window and keep button pressed.
9155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009156 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009157 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9158 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009159 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009160 .build()))
9161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9162 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9163 mWindow->consumeDragEvent(false, 50, 50);
9164 mSecondWindow->assertNoEvents();
9165
9166 // Move to another window and release button, expect to drop item.
9167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009168 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009169 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9170 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009171 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009172 .build()))
9173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9174 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9175 mWindow->assertNoEvents();
9176 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009177 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009178
9179 // nothing to the window.
9180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009181 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009182 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9183 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009184 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009185 .build()))
9186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9187 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9188 mWindow->assertNoEvents();
9189 mSecondWindow->assertNoEvents();
9190}
9191
Arthur Hung54745652022-04-20 07:17:41 +00009192TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009193 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009194
9195 // Set second window invisible.
9196 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009197 mDispatcher->onWindowInfosChanged(
9198 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009199
9200 // Move on window.
9201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009202 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009203 ADISPLAY_ID_DEFAULT, {50, 50}))
9204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9205 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9206 mWindow->consumeDragEvent(false, 50, 50);
9207 mSecondWindow->assertNoEvents();
9208
9209 // Move to another window.
9210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009211 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009212 ADISPLAY_ID_DEFAULT, {150, 50}))
9213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9214 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9215 mWindow->consumeDragEvent(true, 150, 50);
9216 mSecondWindow->assertNoEvents();
9217
9218 // drop to another window.
9219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009220 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009221 {150, 50}))
9222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9223 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009224 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009225 mWindow->assertNoEvents();
9226 mSecondWindow->assertNoEvents();
9227}
9228
Arthur Hung54745652022-04-20 07:17:41 +00009229TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009230 // Ensure window could track pointerIds if it didn't support split touch.
9231 mWindow->setPreventSplitting(true);
9232
Arthur Hung54745652022-04-20 07:17:41 +00009233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009234 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009235 {50, 50}))
9236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9237 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9238
9239 const MotionEvent secondFingerDownEvent =
9240 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9241 .displayId(ADISPLAY_ID_DEFAULT)
9242 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009243 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9244 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009245 .build();
9246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009247 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009248 InputEventInjectionSync::WAIT_FOR_RESULT))
9249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009250 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009251
9252 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009253 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009254}
9255
9256TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9257 // First down on second window.
9258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009259 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009260 {150, 50}))
9261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9262
9263 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9264
9265 // Second down on first window.
9266 const MotionEvent secondFingerDownEvent =
9267 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9268 .displayId(ADISPLAY_ID_DEFAULT)
9269 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009270 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9271 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009272 .build();
9273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009274 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009275 InputEventInjectionSync::WAIT_FOR_RESULT))
9276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9277 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9278
9279 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009280 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009281
9282 // Move on window.
9283 const MotionEvent secondFingerMoveEvent =
9284 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9285 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009286 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9287 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009288 .build();
9289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009290 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009291 InputEventInjectionSync::WAIT_FOR_RESULT));
9292 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9293 mWindow->consumeDragEvent(false, 50, 50);
9294 mSecondWindow->consumeMotionMove();
9295
9296 // Release the drag pointer should perform drop.
9297 const MotionEvent secondFingerUpEvent =
9298 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9299 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009300 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9301 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009302 .build();
9303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009304 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009305 InputEventInjectionSync::WAIT_FOR_RESULT));
9306 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009307 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009308 mWindow->assertNoEvents();
9309 mSecondWindow->consumeMotionMove();
9310}
9311
Arthur Hung3915c1f2022-05-31 07:17:17 +00009312TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009313 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009314
9315 // Update window of second display.
9316 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009317 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009318 mDispatcher->onWindowInfosChanged(
9319 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9320 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9321 {},
9322 0,
9323 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009324
9325 // Let second display has a touch state.
9326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009327 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009328 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9329 AINPUT_SOURCE_TOUCHSCREEN)
9330 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009331 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009332 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009333 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009334 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009335 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009336 mDispatcher->onWindowInfosChanged(
9337 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9338 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9339 {},
9340 0,
9341 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009342
9343 // Move on window.
9344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009345 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009346 ADISPLAY_ID_DEFAULT, {50, 50}))
9347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9348 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9349 mWindow->consumeDragEvent(false, 50, 50);
9350 mSecondWindow->assertNoEvents();
9351
9352 // Move to another window.
9353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009354 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009355 ADISPLAY_ID_DEFAULT, {150, 50}))
9356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9357 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9358 mWindow->consumeDragEvent(true, 150, 50);
9359 mSecondWindow->consumeDragEvent(false, 50, 50);
9360
9361 // drop to another window.
9362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009363 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009364 {150, 50}))
9365 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9366 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009367 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009368 mWindow->assertNoEvents();
9369 mSecondWindow->assertNoEvents();
9370}
9371
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009372TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9373 startDrag(true, AINPUT_SOURCE_MOUSE);
9374 // Move on window.
9375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009376 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009377 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9378 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009379 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009380 .x(50)
9381 .y(50))
9382 .build()))
9383 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9384 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9385 mWindow->consumeDragEvent(false, 50, 50);
9386 mSecondWindow->assertNoEvents();
9387
9388 // Move to another window.
9389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009390 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009391 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9392 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009393 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009394 .x(150)
9395 .y(50))
9396 .build()))
9397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9398 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9399 mWindow->consumeDragEvent(true, 150, 50);
9400 mSecondWindow->consumeDragEvent(false, 50, 50);
9401
9402 // drop to another window.
9403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009404 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009405 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9406 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009407 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009408 .x(150)
9409 .y(50))
9410 .build()))
9411 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9412 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009413 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009414 mWindow->assertNoEvents();
9415 mSecondWindow->assertNoEvents();
9416}
9417
Linnan Li5af92f92023-07-14 14:36:22 +08009418/**
9419 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9420 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9421 */
9422TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9423 // Down on second window
9424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9425 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9426 {150, 50}))
9427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9428
9429 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9430 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9431
9432 // Down on first window
9433 const MotionEvent secondFingerDownEvent =
9434 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9435 .displayId(ADISPLAY_ID_DEFAULT)
9436 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9437 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9438 .build();
9439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9440 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9441 InputEventInjectionSync::WAIT_FOR_RESULT))
9442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9443 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9444 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9445 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9446
9447 // Start drag on first window
9448 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9449
9450 // Trigger cancel
9451 mDispatcher->cancelCurrentTouch();
9452 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9453 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9454 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9455
9456 ASSERT_TRUE(mDispatcher->waitForIdle());
9457 // The D&D finished with nullptr
9458 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9459
9460 // Remove drag window
9461 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9462
9463 // Inject a simple gesture, ensure dispatcher not crashed
9464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9465 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9466 PointF{50, 50}))
9467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9468 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9469
9470 const MotionEvent moveEvent =
9471 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9472 .displayId(ADISPLAY_ID_DEFAULT)
9473 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9474 .build();
9475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9476 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9477 InputEventInjectionSync::WAIT_FOR_RESULT))
9478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9479 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9480
9481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9482 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9483 {50, 50}))
9484 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9485 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9486}
9487
Vishnu Nair062a8672021-09-03 16:07:44 -07009488class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9489
9490TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009492 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9493 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009494 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009495 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9496 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009497 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009498 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009499 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009500
9501 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009502 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009503 window->assertNoEvents();
9504
Prabir Pradhan678438e2023-04-13 19:32:51 +00009505 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9506 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009507 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9508 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009509 window->assertNoEvents();
9510
9511 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009512 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009513 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009514
Prabir Pradhan678438e2023-04-13 19:32:51 +00009515 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009516 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9517
Prabir Pradhan678438e2023-04-13 19:32:51 +00009518 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9519 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009520 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9521 window->assertNoEvents();
9522}
9523
9524TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9525 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9526 std::make_shared<FakeApplicationHandle>();
9527 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009528 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9529 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009530 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009531 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009532 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009534 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9535 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009536 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009537 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009538 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9539 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009540 mDispatcher->onWindowInfosChanged(
9541 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009542 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009543 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009544
9545 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009546 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009547 window->assertNoEvents();
9548
Prabir Pradhan678438e2023-04-13 19:32:51 +00009549 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9550 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009551 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9552 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009553 window->assertNoEvents();
9554
9555 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009556 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009557 mDispatcher->onWindowInfosChanged(
9558 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009559
Prabir Pradhan678438e2023-04-13 19:32:51 +00009560 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009561 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9562
Prabir Pradhan678438e2023-04-13 19:32:51 +00009563 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9564 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009565 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9566 window->assertNoEvents();
9567}
9568
9569TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9570 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9571 std::make_shared<FakeApplicationHandle>();
9572 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009573 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9574 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009575 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009576 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009577 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009579 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9580 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009581 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009582 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009583 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9584 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009585 mDispatcher->onWindowInfosChanged(
9586 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009587 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009588 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009589
9590 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009591 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009592 window->assertNoEvents();
9593
Prabir Pradhan678438e2023-04-13 19:32:51 +00009594 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9595 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009596 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9597 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009598 window->assertNoEvents();
9599
9600 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009601 mDispatcher->onWindowInfosChanged(
9602 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009603
Prabir Pradhan678438e2023-04-13 19:32:51 +00009604 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009605 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9606
Prabir Pradhan678438e2023-04-13 19:32:51 +00009607 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9608 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009609 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9610 window->assertNoEvents();
9611}
9612
Antonio Kantekf16f2832021-09-28 04:39:20 +00009613class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9614protected:
9615 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009616 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009617 sp<FakeWindowHandle> mWindow;
9618 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009619 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009620
9621 void SetUp() override {
9622 InputDispatcherTest::SetUp();
9623
9624 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009625 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009626 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009627 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009628 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009629 mSecondWindow =
9630 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009631 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009632 mThirdWindow =
9633 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9634 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9635 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009636
9637 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009638 mDispatcher->onWindowInfosChanged(
9639 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9640 {},
9641 0,
9642 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009643 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009644 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009645
Antonio Kantek15beb512022-06-13 22:35:41 +00009646 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009647 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009648 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009649 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9650 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009651 mThirdWindow->assertNoEvents();
9652 }
9653
9654 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9655 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009656 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009657 SECOND_DISPLAY_ID)) {
9658 mWindow->assertNoEvents();
9659 mSecondWindow->assertNoEvents();
9660 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009661 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009662 }
9663
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009664 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009665 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009666 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9667 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009668 mWindow->consumeTouchModeEvent(inTouchMode);
9669 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009670 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009671 }
9672};
9673
Antonio Kantek26defcf2022-02-08 01:12:27 +00009674TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009675 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009676 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9677 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009678 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009679}
9680
Antonio Kantek26defcf2022-02-08 01:12:27 +00009681TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9682 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009683 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009684 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009685 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009686 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009687 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009688 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009689 mWindow->assertNoEvents();
9690 mSecondWindow->assertNoEvents();
9691}
9692
9693TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9694 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009695 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009696 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009697 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009698 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009699 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009700}
9701
Antonio Kantekf16f2832021-09-28 04:39:20 +00009702TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009703 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009704 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9705 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009706 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009707 mWindow->assertNoEvents();
9708 mSecondWindow->assertNoEvents();
9709}
9710
Antonio Kantek15beb512022-06-13 22:35:41 +00009711TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9712 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9713 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9714 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009715 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009716 mWindow->assertNoEvents();
9717 mSecondWindow->assertNoEvents();
9718 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9719}
9720
Antonio Kantek48710e42022-03-24 14:19:30 -07009721TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9722 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9724 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009725 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9726 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9727
9728 // Then remove focus.
9729 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009730 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009731
9732 // Assert that caller can switch touch mode by owning one of the last interacted window.
9733 const WindowInfo& windowInfo = *mWindow->getInfo();
9734 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9735 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009736 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009737}
9738
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009739class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9740public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009741 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009742 std::shared_ptr<FakeApplicationHandle> application =
9743 std::make_shared<FakeApplicationHandle>();
9744 std::string name = "Fake Spy ";
9745 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009746 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9747 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009748 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009749 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009750 return spy;
9751 }
9752
9753 sp<FakeWindowHandle> createForeground() {
9754 std::shared_ptr<FakeApplicationHandle> application =
9755 std::make_shared<FakeApplicationHandle>();
9756 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009757 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9758 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009759 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009760 return window;
9761 }
9762
9763private:
9764 int mSpyCount{0};
9765};
9766
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009767using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009768/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009769 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9770 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009771TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009772 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009773 ScopedSilentDeath _silentDeath;
9774
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009775 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009776 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009777 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009778 ".* not a trusted overlay");
9779}
9780
9781/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009782 * Input injection into a display with a spy window but no foreground windows should succeed.
9783 */
9784TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009785 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009786 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009787
9788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9791 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9792}
9793
9794/**
9795 * Verify the order in which different input windows receive events. The touched foreground window
9796 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9797 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9798 * receive events before ones belows it.
9799 *
9800 * Here, we set up a scenario with four windows in the following Z order from the top:
9801 * spy1, spy2, window, spy3.
9802 * We then inject an event and verify that the foreground "window" receives it first, followed by
9803 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9804 * window.
9805 */
9806TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9807 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009808 auto spy1 = createSpy();
9809 auto spy2 = createSpy();
9810 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009811 mDispatcher->onWindowInfosChanged(
9812 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009813 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9814 const size_t numChannels = channels.size();
9815
Michael Wright8e9a8562022-02-09 13:44:29 +00009816 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009817 if (!epollFd.ok()) {
9818 FAIL() << "Failed to create epoll fd";
9819 }
9820
9821 for (size_t i = 0; i < numChannels; i++) {
9822 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9823 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9824 FAIL() << "Failed to add fd to epoll";
9825 }
9826 }
9827
9828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009829 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9831
9832 std::vector<size_t> eventOrder;
9833 std::vector<struct epoll_event> events(numChannels);
9834 for (;;) {
9835 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9836 (100ms).count());
9837 if (nFds < 0) {
9838 FAIL() << "Failed to call epoll_wait";
9839 }
9840 if (nFds == 0) {
9841 break; // epoll_wait timed out
9842 }
9843 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009844 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009845 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009846 channels[i]->consumeMotionDown();
9847 }
9848 }
9849
9850 // Verify the order in which the events were received.
9851 EXPECT_EQ(3u, eventOrder.size());
9852 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9853 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9854 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9855}
9856
9857/**
9858 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9859 */
9860TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9861 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009862 auto spy = createSpy();
9863 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009864 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009865
9866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009867 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9869 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9870 spy->assertNoEvents();
9871}
9872
9873/**
9874 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9875 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9876 * to the window.
9877 */
9878TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9879 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009880 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009881 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009882 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009883
9884 // Inject an event outside the spy window's touchable region.
9885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009886 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9888 window->consumeMotionDown();
9889 spy->assertNoEvents();
9890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009891 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9893 window->consumeMotionUp();
9894 spy->assertNoEvents();
9895
9896 // Inject an event inside the spy window's touchable region.
9897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009898 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009899 {5, 10}))
9900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9901 window->consumeMotionDown();
9902 spy->consumeMotionDown();
9903}
9904
9905/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009906 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009907 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009908 */
9909TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9910 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009911 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009912 auto spy = createSpy();
9913 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009914 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009915 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009916 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009917
9918 // Inject an event outside the spy window's frame and touchable region.
9919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009920 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009921 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9923 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009924 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009925}
9926
9927/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009928 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9929 * pointers that are down within its bounds.
9930 */
9931TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9932 auto windowLeft = createForeground();
9933 windowLeft->setFrame({0, 0, 100, 200});
9934 auto windowRight = createForeground();
9935 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009936 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009937 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009938 mDispatcher->onWindowInfosChanged(
9939 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009940
9941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009942 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009943 {50, 50}))
9944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9945 windowLeft->consumeMotionDown();
9946 spy->consumeMotionDown();
9947
9948 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009949 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009950 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009951 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9952 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009953 .build();
9954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009955 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009956 InputEventInjectionSync::WAIT_FOR_RESULT))
9957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9958 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009959 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009960}
9961
9962/**
9963 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9964 * the spy should receive the second pointer with ACTION_DOWN.
9965 */
9966TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9967 auto window = createForeground();
9968 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009969 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009970 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009971 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009972
9973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009974 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009975 {50, 50}))
9976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9977 window->consumeMotionDown();
9978 spyRight->assertNoEvents();
9979
9980 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009981 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009982 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009983 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9984 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009985 .build();
9986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009987 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009988 InputEventInjectionSync::WAIT_FOR_RESULT))
9989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009990 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009991 spyRight->consumeMotionDown();
9992}
9993
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009994/**
9995 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9996 * windows should be allowed to control split touch.
9997 */
9998TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009999 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010000 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010001 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010002 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010003
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010004 auto window = createForeground();
10005 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010006
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010007 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010008
10009 // First finger down, no window touched.
10010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010011 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010012 {100, 200}))
10013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10014 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10015 window->assertNoEvents();
10016
10017 // Second finger down on window, the window should receive touch down.
10018 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010019 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010020 .displayId(ADISPLAY_ID_DEFAULT)
10021 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010022 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10023 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010024 .build();
10025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010026 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010027 InputEventInjectionSync::WAIT_FOR_RESULT))
10028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10029
10030 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010031 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010032}
10033
10034/**
10035 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10036 * do not receive key events.
10037 */
10038TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010039 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010040 spy->setFocusable(false);
10041
10042 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010043 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010044 setFocusedWindow(window);
10045 window->consumeFocusEvent(true);
10046
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010048 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10049 window->consumeKeyDown(ADISPLAY_ID_NONE);
10050
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010052 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10053 window->consumeKeyUp(ADISPLAY_ID_NONE);
10054
10055 spy->assertNoEvents();
10056}
10057
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010058using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10059
10060/**
10061 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10062 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10063 */
10064TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10065 auto window = createForeground();
10066 auto spy1 = createSpy();
10067 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010068 mDispatcher->onWindowInfosChanged(
10069 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010070
10071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010072 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10074 window->consumeMotionDown();
10075 spy1->consumeMotionDown();
10076 spy2->consumeMotionDown();
10077
10078 // Pilfer pointers from the second spy window.
10079 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10080 spy2->assertNoEvents();
10081 spy1->consumeMotionCancel();
10082 window->consumeMotionCancel();
10083
10084 // The rest of the gesture should only be sent to the second spy window.
10085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010086 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010087 ADISPLAY_ID_DEFAULT))
10088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10089 spy2->consumeMotionMove();
10090 spy1->assertNoEvents();
10091 window->assertNoEvents();
10092}
10093
10094/**
10095 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10096 * in the middle of the gesture.
10097 */
10098TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10099 auto window = createForeground();
10100 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010101 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010102
10103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010104 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010105 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10106 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10107 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10108
10109 window->releaseChannel();
10110
10111 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10112
10113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010114 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10116 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10117}
10118
10119/**
10120 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10121 * the spy, but not to any other windows.
10122 */
10123TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10124 auto spy = createSpy();
10125 auto window = createForeground();
10126
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010127 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010128
10129 // First finger down on the window and the spy.
10130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010131 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010132 {100, 200}))
10133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10134 spy->consumeMotionDown();
10135 window->consumeMotionDown();
10136
10137 // Spy window pilfers the pointers.
10138 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10139 window->consumeMotionCancel();
10140
10141 // Second finger down on the window and spy, but the window should not receive the pointer down.
10142 const MotionEvent secondFingerDownEvent =
10143 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10144 .displayId(ADISPLAY_ID_DEFAULT)
10145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010146 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10147 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010148 .build();
10149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010150 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010151 InputEventInjectionSync::WAIT_FOR_RESULT))
10152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10153
Harry Cutts33476232023-01-30 19:57:29 +000010154 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010155
10156 // Third finger goes down outside all windows, so injection should fail.
10157 const MotionEvent thirdFingerDownEvent =
10158 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10159 .displayId(ADISPLAY_ID_DEFAULT)
10160 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010161 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10162 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10163 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010164 .build();
10165 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010166 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010167 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010168 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010169
10170 spy->assertNoEvents();
10171 window->assertNoEvents();
10172}
10173
10174/**
10175 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10176 */
10177TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10178 auto spy = createSpy();
10179 spy->setFrame(Rect(0, 0, 100, 100));
10180 auto window = createForeground();
10181 window->setFrame(Rect(0, 0, 200, 200));
10182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010183 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010184
10185 // First finger down on the window only
10186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010187 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010188 {150, 150}))
10189 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10190 window->consumeMotionDown();
10191
10192 // Second finger down on the spy and window
10193 const MotionEvent secondFingerDownEvent =
10194 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10195 .displayId(ADISPLAY_ID_DEFAULT)
10196 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010197 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10198 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010199 .build();
10200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010201 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010202 InputEventInjectionSync::WAIT_FOR_RESULT))
10203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10204 spy->consumeMotionDown();
10205 window->consumeMotionPointerDown(1);
10206
10207 // Third finger down on the spy and window
10208 const MotionEvent thirdFingerDownEvent =
10209 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10210 .displayId(ADISPLAY_ID_DEFAULT)
10211 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010212 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10213 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10214 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010215 .build();
10216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010217 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010218 InputEventInjectionSync::WAIT_FOR_RESULT))
10219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10220 spy->consumeMotionPointerDown(1);
10221 window->consumeMotionPointerDown(2);
10222
10223 // Spy window pilfers the pointers.
10224 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010225 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10226 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010227
10228 spy->assertNoEvents();
10229 window->assertNoEvents();
10230}
10231
10232/**
10233 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10234 * other windows should be canceled. If this results in the cancellation of all pointers for some
10235 * window, then that window should receive ACTION_CANCEL.
10236 */
10237TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10238 auto spy = createSpy();
10239 spy->setFrame(Rect(0, 0, 100, 100));
10240 auto window = createForeground();
10241 window->setFrame(Rect(0, 0, 200, 200));
10242
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010243 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010244
10245 // First finger down on both spy and window
10246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010247 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010248 {10, 10}))
10249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10250 window->consumeMotionDown();
10251 spy->consumeMotionDown();
10252
10253 // Second finger down on the spy and window
10254 const MotionEvent secondFingerDownEvent =
10255 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10256 .displayId(ADISPLAY_ID_DEFAULT)
10257 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010258 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10259 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010260 .build();
10261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010262 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010263 InputEventInjectionSync::WAIT_FOR_RESULT))
10264 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10265 spy->consumeMotionPointerDown(1);
10266 window->consumeMotionPointerDown(1);
10267
10268 // Spy window pilfers the pointers.
10269 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10270 window->consumeMotionCancel();
10271
10272 spy->assertNoEvents();
10273 window->assertNoEvents();
10274}
10275
10276/**
10277 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10278 * be sent to other windows
10279 */
10280TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10281 auto spy = createSpy();
10282 spy->setFrame(Rect(0, 0, 100, 100));
10283 auto window = createForeground();
10284 window->setFrame(Rect(0, 0, 200, 200));
10285
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010286 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010287
10288 // First finger down on both window and spy
10289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010290 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010291 {10, 10}))
10292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10293 window->consumeMotionDown();
10294 spy->consumeMotionDown();
10295
10296 // Spy window pilfers the pointers.
10297 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10298 window->consumeMotionCancel();
10299
10300 // Second finger down on the window only
10301 const MotionEvent secondFingerDownEvent =
10302 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10303 .displayId(ADISPLAY_ID_DEFAULT)
10304 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010305 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10306 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010307 .build();
10308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010309 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010310 InputEventInjectionSync::WAIT_FOR_RESULT))
10311 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10312 window->consumeMotionDown();
10313 window->assertNoEvents();
10314
10315 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10316 spy->consumeMotionMove();
10317 spy->assertNoEvents();
10318}
10319
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010320/**
10321 * A window on the left and a window on the right. Also, a spy window that's above all of the
10322 * windows, and spanning both left and right windows.
10323 * Send simultaneous motion streams from two different devices, one to the left window, and another
10324 * to the right window.
10325 * Pilfer from spy window.
10326 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10327 */
10328TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10329 sp<FakeWindowHandle> spy = createSpy();
10330 spy->setFrame(Rect(0, 0, 200, 200));
10331 sp<FakeWindowHandle> leftWindow = createForeground();
10332 leftWindow->setFrame(Rect(0, 0, 100, 100));
10333
10334 sp<FakeWindowHandle> rightWindow = createForeground();
10335 rightWindow->setFrame(Rect(100, 0, 200, 100));
10336
10337 constexpr int32_t stylusDeviceId = 1;
10338 constexpr int32_t touchDeviceId = 2;
10339
10340 mDispatcher->onWindowInfosChanged(
10341 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10342
10343 // Stylus down on left window and spy
10344 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10345 .deviceId(stylusDeviceId)
10346 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10347 .build());
10348 leftWindow->consumeMotionEvent(
10349 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10350 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10351
10352 // Finger down on right window and spy - but spy already has stylus
10353 mDispatcher->notifyMotion(
10354 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10355 .deviceId(touchDeviceId)
10356 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10357 .build());
10358 rightWindow->consumeMotionEvent(
10359 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10360 leftWindow->consumeMotionEvent(
10361 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10362 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10363 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10364
10365 // Act: pilfer from spy. Spy is currently receiving touch events.
10366 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10367 rightWindow->consumeMotionEvent(
10368 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10369
10370 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10371 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10372 .deviceId(stylusDeviceId)
10373 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10374 .build());
10375 mDispatcher->notifyMotion(
10376 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10377 .deviceId(touchDeviceId)
10378 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10379 .build());
10380 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10381
10382 spy->assertNoEvents();
10383 leftWindow->assertNoEvents();
10384 rightWindow->assertNoEvents();
10385}
10386
Prabir Pradhand65552b2021-10-07 11:23:50 -070010387class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10388public:
10389 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10390 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10391 std::make_shared<FakeApplicationHandle>();
10392 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010393 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10394 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010395 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010396 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010397 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010398 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010399 overlay->setTrustedOverlay(true);
10400
10401 std::shared_ptr<FakeApplicationHandle> application =
10402 std::make_shared<FakeApplicationHandle>();
10403 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010404 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10405 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010406 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010407 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010408
10409 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010410 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010411 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010412 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010413 return {std::move(overlay), std::move(window)};
10414 }
10415
10416 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010417 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010418 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010419 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010420 }
10421
10422 void sendStylusEvent(int32_t action) {
10423 NotifyMotionArgs motionArgs =
10424 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10425 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010426 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010427 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010428 }
10429};
10430
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010431using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10432
10433TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010434 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010435 ScopedSilentDeath _silentDeath;
10436
Prabir Pradhand65552b2021-10-07 11:23:50 -070010437 auto [overlay, window] = setupStylusOverlayScenario();
10438 overlay->setTrustedOverlay(false);
10439 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010440 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10441 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010442 ".* not a trusted overlay");
10443}
10444
10445TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10446 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010447 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010448
10449 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10450 overlay->consumeMotionDown();
10451 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10452 overlay->consumeMotionUp();
10453
10454 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10455 window->consumeMotionDown();
10456 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10457 window->consumeMotionUp();
10458
10459 overlay->assertNoEvents();
10460 window->assertNoEvents();
10461}
10462
10463TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10464 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010465 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010466 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010467
10468 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10469 overlay->consumeMotionDown();
10470 window->consumeMotionDown();
10471 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10472 overlay->consumeMotionUp();
10473 window->consumeMotionUp();
10474
10475 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10476 window->consumeMotionDown();
10477 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10478 window->consumeMotionUp();
10479
10480 overlay->assertNoEvents();
10481 window->assertNoEvents();
10482}
10483
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010484/**
10485 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10486 * The scenario is as follows:
10487 * - The stylus interceptor overlay is configured as a spy window.
10488 * - The stylus interceptor spy receives the start of a new stylus gesture.
10489 * - It pilfers pointers and then configures itself to no longer be a spy.
10490 * - The stylus interceptor continues to receive the rest of the gesture.
10491 */
10492TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10493 auto [overlay, window] = setupStylusOverlayScenario();
10494 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010495 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010496
10497 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10498 overlay->consumeMotionDown();
10499 window->consumeMotionDown();
10500
10501 // The interceptor pilfers the pointers.
10502 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10503 window->consumeMotionCancel();
10504
10505 // The interceptor configures itself so that it is no longer a spy.
10506 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010507 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010508
10509 // It continues to receive the rest of the stylus gesture.
10510 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10511 overlay->consumeMotionMove();
10512 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10513 overlay->consumeMotionUp();
10514
10515 window->assertNoEvents();
10516}
10517
Prabir Pradhan5735a322022-04-11 17:23:34 +000010518struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010519 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010520 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010521 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10522 std::unique_ptr<InputDispatcher>& mDispatcher;
10523
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010524 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010525 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10526
10527 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010528 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010529 ADISPLAY_ID_DEFAULT, {100, 200},
10530 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10531 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10532 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10533 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10534 }
10535
10536 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010537 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010538 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010539 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010540 mPolicyFlags);
10541 }
10542
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010543 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010544 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10545 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010546 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10547 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010548 window->setOwnerInfo(mPid, mUid);
10549 return window;
10550 }
10551};
10552
10553using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10554
10555TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010556 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010557 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010558 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010559
10560 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10561 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10562 window->consumeMotionDown();
10563
10564 setFocusedWindow(window);
10565 window->consumeFocusEvent(true);
10566
10567 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10568 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10569 window->consumeKeyDown(ADISPLAY_ID_NONE);
10570}
10571
10572TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010573 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010574 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010575 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010576
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010577 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010578 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10579 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10580
10581 setFocusedWindow(window);
10582 window->consumeFocusEvent(true);
10583
10584 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10585 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10586 window->assertNoEvents();
10587}
10588
10589TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010590 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010591 auto window = owner.createWindow("Owned window");
10592 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010593 spy->setSpy(true);
10594 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010595 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010596
10597 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10598 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10599 spy->consumeMotionDown();
10600 window->consumeMotionDown();
10601}
10602
10603TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010604 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010605 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010606
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010607 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010608 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010609 randosSpy->setSpy(true);
10610 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010611 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010612
10613 // The event is targeted at owner's window, so injection should succeed, but the spy should
10614 // not receive the event.
10615 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10616 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10617 randosSpy->assertNoEvents();
10618 window->consumeMotionDown();
10619}
10620
10621TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010622 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010623 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010624
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010625 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010626 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010627 randosSpy->setSpy(true);
10628 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010629 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010630
10631 // A user that has injection permission can inject into any window.
10632 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010633 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010634 ADISPLAY_ID_DEFAULT));
10635 randosSpy->consumeMotionDown();
10636 window->consumeMotionDown();
10637
10638 setFocusedWindow(randosSpy);
10639 randosSpy->consumeFocusEvent(true);
10640
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010641 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010642 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10643 window->assertNoEvents();
10644}
10645
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010646TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010647 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010648 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010649
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010650 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010651 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010652 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10653 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010654 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010655
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010656 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010657 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10658 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10659 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010660 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010661}
10662
Garfield Tane84e6f92019-08-29 17:28:41 -070010663} // namespace android::inputdispatcher