blob: 395ce038264cf2694828476a854982928a325ab5 [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
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800187MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700188 *result_listener << "expected pointerCount " << pointerCount << ", but got "
189 << arg.getPointerCount();
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800190 return arg.getPointerCount() == pointerCount;
191}
192
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800193MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
194 // Build a map for the received pointers, by pointer id
195 std::map<int32_t /*pointerId*/, PointF> actualPointers;
196 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
197 const int32_t pointerId = arg.getPointerId(pointerIndex);
198 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
199 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700200 *result_listener << "expected pointers " << dumpMap(pointers, constToString, pointFToString)
201 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800202 return pointers == actualPointers;
203}
204
Michael Wrightd02c5b62014-02-10 15:10:22 -0800205// --- FakeInputDispatcherPolicy ---
206
207class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000208 struct AnrResult {
209 sp<IBinder> token{};
210 gui::Pid pid{gui::Pid::INVALID};
211 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800212
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000214 FakeInputDispatcherPolicy() = default;
215 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800216
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800217 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700218 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700219 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700220 EXPECT_EQ(event.getDisplayId(), args.displayId);
221
222 const auto& keyEvent = static_cast<const KeyEvent&>(event);
223 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
224 EXPECT_EQ(keyEvent.getAction(), args.action);
225 });
Jackal Guof9696682018-10-05 12:23:23 +0800226 }
227
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
229 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700230 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700231 EXPECT_EQ(event.getDisplayId(), args.displayId);
232
233 const auto& motionEvent = static_cast<const MotionEvent&>(event);
234 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
235 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000236 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
237 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700240 });
Jackal Guof9696682018-10-05 12:23:23 +0800241 }
242
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700243 void assertFilterInputEventWasNotCalled() {
244 std::scoped_lock lock(mLock);
245 ASSERT_EQ(nullptr, mFilteredEvent);
246 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700249 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800250 ASSERT_TRUE(mConfigurationChangedTime)
251 << "Timed out waiting for configuration changed call";
252 ASSERT_EQ(*mConfigurationChangedTime, when);
253 mConfigurationChangedTime = std::nullopt;
254 }
255
256 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700257 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800258 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800259 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800260 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
261 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
262 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
263 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
264 mLastNotifySwitch = std::nullopt;
265 }
266
chaviwfd6d3512019-03-25 13:23:49 -0700267 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700268 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800269 ASSERT_EQ(touchedToken, mOnPointerDownToken);
270 mOnPointerDownToken.clear();
271 }
272
273 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700274 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800275 ASSERT_TRUE(mOnPointerDownToken == nullptr)
276 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700277 }
278
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700279 // This function must be called soon after the expected ANR timer starts,
280 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700282 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_NO_FATAL_FAILURE(
288 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700290 }
291
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000292 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800293 const sp<WindowInfoHandle>& window) {
294 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
295 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
296 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500297 }
298
Prabir Pradhanedd96402022-02-15 01:46:16 -0800299 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
300 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000301 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800302 std::unique_lock lock(mLock);
303 android::base::ScopedLockAssertion assumeLocked(mLock);
304 AnrResult result;
305 ASSERT_NO_FATAL_FAILURE(result =
306 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000307 ASSERT_EQ(expectedToken, result.token);
308 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500309 }
310
Prabir Pradhanedd96402022-02-15 01:46:16 -0800311 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000312 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500313 std::unique_lock lock(mLock);
314 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800315 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
316 const auto& [token, _] = result;
317 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000318 }
319
Prabir Pradhanedd96402022-02-15 01:46:16 -0800320 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000321 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800322 std::unique_lock lock(mLock);
323 android::base::ScopedLockAssertion assumeLocked(mLock);
324 AnrResult result;
325 ASSERT_NO_FATAL_FAILURE(
326 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000327 ASSERT_EQ(expectedToken, result.token);
328 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800329 }
330
331 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000332 sp<IBinder> getResponsiveWindowToken() {
333 std::unique_lock lock(mLock);
334 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800335 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
336 const auto& [token, _] = result;
337 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700338 }
339
340 void assertNotifyAnrWasNotCalled() {
341 std::scoped_lock lock(mLock);
342 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800343 ASSERT_TRUE(mAnrWindows.empty());
344 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500345 << "ANR was not called, but please also consume the 'connection is responsive' "
346 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700347 }
348
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000349 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800350 std::unique_lock lock(mLock);
351 base::ScopedLockAssertion assumeLocked(mLock);
352
353 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
354 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000355 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800356 enabled;
357 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000358 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
359 << ") to be called.";
360 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800361 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 auto request = *mPointerCaptureRequest;
363 mPointerCaptureRequest.reset();
364 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800365 }
366
367 void assertSetPointerCaptureNotCalled() {
368 std::unique_lock lock(mLock);
369 base::ScopedLockAssertion assumeLocked(mLock);
370
371 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000372 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800373 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
378
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700379 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
380 const sp<IBinder>& targetToken) {
381 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800382 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800383 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800384 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800386 }
387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800388 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
389 std::unique_lock lock(mLock);
390 base::ScopedLockAssertion assumeLocked(mLock);
391 std::optional<sp<IBinder>> receivedToken =
392 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
393 mNotifyInputChannelBroken);
394 ASSERT_TRUE(receivedToken.has_value());
395 ASSERT_EQ(token, *receivedToken);
396 }
397
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800398 /**
399 * Set policy timeout. A value of zero means next key will not be intercepted.
400 */
401 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
402 mInterceptKeyTimeout = timeout;
403 }
404
Josep del Riob3981622023-04-18 15:49:45 +0000405 void assertUserActivityPoked() {
406 std::scoped_lock lock(mLock);
407 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
408 }
409
410 void assertUserActivityNotPoked() {
411 std::scoped_lock lock(mLock);
412 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
413 }
414
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000415 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000416 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
417 }
418
419 void assertNotifyDeviceInteractionWasNotCalled() {
420 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
421 }
422
Michael Wrightd02c5b62014-02-10 15:10:22 -0800423private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700424 std::mutex mLock;
425 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
426 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
427 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
428 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800429
Prabir Pradhan99987712020-11-10 18:43:05 -0800430 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000431
432 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800433
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700434 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700435 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800436 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
437 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700438 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800439 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
440 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700441
arthurhungf452d0b2021-01-06 00:19:52 +0800442 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800443 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000444 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800445
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800446 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
447
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000448 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000449
Prabir Pradhanedd96402022-02-15 01:46:16 -0800450 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
451 // for a specific container to become non-empty. When the container is non-empty, return the
452 // first entry from the container and erase it.
453 template <class T>
454 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
455 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
456 // If there is an ANR, Dispatcher won't be idle because there are still events
457 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
458 // before checking if ANR was called.
459 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
460 // to provide it some time to act. 100ms seems reasonable.
461 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
462 const std::chrono::time_point start = std::chrono::steady_clock::now();
463 std::optional<T> token =
464 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
465 if (!token.has_value()) {
466 ADD_FAILURE() << "Did not receive the ANR callback";
467 return {};
468 }
469
470 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
471 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
472 // the dispatcher started counting before this function was called
473 if (std::chrono::abs(timeout - waited) > 100ms) {
474 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
475 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
476 << "ms, but waited "
477 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
478 << "ms instead";
479 }
480 return *token;
481 }
482
483 template <class T>
484 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
485 std::queue<T>& storage,
486 std::unique_lock<std::mutex>& lock,
487 std::condition_variable& condition)
488 REQUIRES(mLock) {
489 condition.wait_for(lock, timeout,
490 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
491 if (storage.empty()) {
492 ADD_FAILURE() << "Did not receive the expected callback";
493 return std::nullopt;
494 }
495 T item = storage.front();
496 storage.pop();
497 return std::make_optional(item);
498 }
499
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600500 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700501 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800502 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800503 }
504
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000505 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800506 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700507 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800508 ASSERT_TRUE(pid.has_value());
509 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700510 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500511 }
512
Prabir Pradhanedd96402022-02-15 01:46:16 -0800513 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000514 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500515 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800516 ASSERT_TRUE(pid.has_value());
517 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500518 mNotifyAnr.notify_all();
519 }
520
521 void notifyNoFocusedWindowAnr(
522 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
523 std::scoped_lock lock(mLock);
524 mAnrApplications.push(applicationHandle);
525 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800526 }
527
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800528 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
529 std::scoped_lock lock(mLock);
530 mBrokenInputChannels.push(connectionToken);
531 mNotifyInputChannelBroken.notify_all();
532 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800533
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600534 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700535
Chris Yef59a2f42020-10-16 12:55:26 -0700536 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
537 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
538 const std::vector<float>& values) override {}
539
540 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
541 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000542
Chris Yefb552902021-02-03 17:18:37 -0800543 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700546 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000547 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700548 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000549 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
550 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800551 break;
552 }
553
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700554 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000555 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
556 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800557 break;
558 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700559 default: {
560 ADD_FAILURE() << "Should only filter keys or motions";
561 break;
562 }
Jackal Guof9696682018-10-05 12:23:23 +0800563 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800564 return true;
565 }
566
Prabir Pradhana41d2442023-04-20 21:30:40 +0000567 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
568 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800569 // Clear intercept state when we handled the event.
570 mInterceptKeyTimeout = 0ms;
571 }
572 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600574 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575
Prabir Pradhana41d2442023-04-20 21:30:40 +0000576 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800577 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
578 // Clear intercept state so we could dispatch the event in next wake.
579 mInterceptKeyTimeout = 0ms;
580 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 }
582
Prabir Pradhana41d2442023-04-20 21:30:40 +0000583 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
584 uint32_t) override {
585 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586 }
587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
589 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700590 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800591 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
592 * essentially a passthrough for notifySwitch.
593 */
Harry Cutts33476232023-01-30 19:57:29 +0000594 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800595 }
596
Josep del Riob3981622023-04-18 15:49:45 +0000597 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
598 std::scoped_lock lock(mLock);
599 mPokedUserActivity = true;
600 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800601
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600602 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700603 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700604 mOnPointerDownToken = newToken;
605 }
606
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000607 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800608 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000609 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800610 mPointerCaptureChangedCondition.notify_all();
611 }
612
arthurhungf452d0b2021-01-06 00:19:52 +0800613 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
614 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800615 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800616 mDropTargetWindowToken = token;
617 }
618
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000619 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000620 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000621 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
622 }
623
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700624 void assertFilterInputEventWasCalledInternal(
625 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700626 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800627 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700628 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800629 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800630 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800631};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700632} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634// --- InputDispatcherTest ---
635
636class InputDispatcherTest : public testing::Test {
637protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000641 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000642 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
643 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000644 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000645 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700646 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800647 }
648
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000649 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700650 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000651 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700652 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700654
655 /**
656 * Used for debugging when writing the test
657 */
658 void dumpDispatcherState() {
659 std::string dump;
660 mDispatcher->dump(dump);
661 std::stringstream ss(dump);
662 std::string to;
663
664 while (std::getline(ss, to, '\n')) {
665 ALOGE("%s", to.c_str());
666 }
667 }
Vishnu Nair958da932020-08-21 17:12:37 -0700668
Chavi Weingarten847e8512023-03-29 00:26:09 +0000669 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700670 FocusRequest request;
671 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000672 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700673 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
674 request.displayId = window->getInfo()->displayId;
675 mDispatcher->setFocusedWindow(request);
676 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677};
678
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
680 KeyEvent event;
681
682 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800683 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
684 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000685 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600686 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800687 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000688 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000689 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 << "Should reject key events with undefined action.";
691
692 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
694 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600695 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000697 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 << "Should reject key events with ACTION_MULTIPLE.";
700}
701
702TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
703 MotionEvent event;
704 PointerProperties pointerProperties[MAX_POINTERS + 1];
705 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800706 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800707 pointerProperties[i].clear();
708 pointerProperties[i].id = i;
709 pointerCoords[i].clear();
710 }
711
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800712 // Some constants commonly used below
713 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
714 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
715 constexpr int32_t metaState = AMETA_NONE;
716 constexpr MotionClassification classification = MotionClassification::NONE;
717
chaviw9eaa22c2020-07-01 16:21:27 -0700718 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800719 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700722 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700723 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
724 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000725 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800726 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000727 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000728 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800729 << "Should reject motion events with undefined action.";
730
731 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800732 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800733 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
734 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
735 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
736 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000737 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000739 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000740 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800741 << "Should reject motion events with pointer down index too large.";
742
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700744 AMOTION_EVENT_ACTION_POINTER_DOWN |
745 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700746 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
747 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700748 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with pointer down index too small.";
754
755 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800757 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
758 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
759 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
760 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with pointer up index too large.";
766
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700768 AMOTION_EVENT_ACTION_POINTER_UP |
769 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700770 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer up index too small.";
778
779 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
781 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
784 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with 0 pointers.";
790
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with more than MAX_POINTERS pointers.";
801
802 // Rejects motion events with invalid pointer ids.
803 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800804 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
805 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700806 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700807 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
808 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000809 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000811 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000812 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800813 << "Should reject motion events with pointer ids less than 0.";
814
815 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
826
827 // Rejects motion events with duplicate pointer ids.
828 pointerProperties[0].id = 1;
829 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800830 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
831 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700832 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700833 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
834 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000835 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000838 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800839 << "Should reject motion events with duplicate pointer ids.";
840}
841
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
843
844TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
845 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000846 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800847 ASSERT_TRUE(mDispatcher->waitForIdle());
848
849 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
850}
851
852TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000853 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
854 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000855 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800856
857 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
858 args.policyFlags |= POLICY_FLAG_TRUSTED;
859 mFakePolicy->assertNotifySwitchWasCalled(args);
860}
861
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700862namespace {
863
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700864static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700865// Default input dispatching timeout if there is no focused application or paused window
866// from which to determine an appropriate dispatching timeout.
867static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
868 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
869 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800870
871class FakeApplicationHandle : public InputApplicationHandle {
872public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 FakeApplicationHandle() {
874 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700875 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500876 mInfo.dispatchingTimeoutMillis =
877 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700878 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800879 virtual ~FakeApplicationHandle() {}
880
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000881 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500883 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
884 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800886};
887
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800888class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800889public:
Garfield Tan15601662020-09-22 15:32:38 -0700890 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800891 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700892 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800893 }
894
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700895 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700897 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700898 if (!consumeSeq) {
899 return nullptr;
900 }
901 finishEvent(*consumeSeq);
902 return event;
903 }
904
905 /**
906 * Receive an event without acknowledging it.
907 * Return the sequence number that could later be used to send finished signal.
908 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700909 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
910 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800911 uint32_t consumeSeq;
912 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800913
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800914 std::chrono::time_point start = std::chrono::steady_clock::now();
915 status_t status = WOULD_BLOCK;
916 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000917 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800918 &event);
919 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700920 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800921 break;
922 }
923 }
924
925 if (status == WOULD_BLOCK) {
926 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700927 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928 }
929
930 if (status != OK) {
931 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700932 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 }
934 if (event == nullptr) {
935 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700936 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 if (outEvent != nullptr) {
939 *outEvent = event;
940 }
941 return consumeSeq;
942 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 /**
945 * To be used together with "receiveEvent" to complete the consumption of an event.
946 */
947 void finishEvent(uint32_t consumeSeq) {
948 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
949 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800950 }
951
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000952 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
953 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
954 ASSERT_EQ(OK, status);
955 }
956
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700957 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000958 std::optional<int32_t> expectedDisplayId,
959 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700960 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800961
962 ASSERT_NE(nullptr, event) << mName.c_str()
963 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800964 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
966 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800967
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000968 if (expectedDisplayId.has_value()) {
969 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
970 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800971
Tiger Huang8664f8c2018-10-11 19:14:35 +0800972 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800974 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700975 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976 if (expectedFlags.has_value()) {
977 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
978 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979 break;
980 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800982 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700983 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000984 if (expectedFlags.has_value()) {
985 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
986 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 break;
988 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
991 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700992 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800993 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
994 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700995 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000996 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
997 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800999 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1000 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001001 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001002 }
1003
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001004 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001005 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001006
1007 if (event == nullptr) {
1008 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1009 return nullptr;
1010 }
1011
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 if (event->getType() != InputEventType::MOTION) {
1013 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001014 return nullptr;
1015 }
1016 return static_cast<MotionEvent*>(event);
1017 }
1018
1019 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1020 MotionEvent* motionEvent = consumeMotion();
1021 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1022 ASSERT_THAT(*motionEvent, matcher);
1023 }
1024
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001025 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001026 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001027 ASSERT_NE(nullptr, event) << mName.c_str()
1028 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001029 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1030 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001031
1032 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1033 << mName.c_str() << ": event displayId should always be NONE.";
1034
1035 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1036 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001037 }
1038
Prabir Pradhan99987712020-11-10 18:43:05 -08001039 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001040 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001041 ASSERT_NE(nullptr, event) << mName.c_str()
1042 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1044 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001045
1046 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1047 << mName.c_str() << ": event displayId should always be NONE.";
1048
1049 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1050 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1051 }
1052
arthurhungb89ccb02020-12-30 16:19:01 +08001053 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001054 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001055 ASSERT_NE(nullptr, event) << mName.c_str()
1056 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001057 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001058
1059 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1060 << mName.c_str() << ": event displayId should always be NONE.";
1061
1062 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1063 EXPECT_EQ(isExiting, dragEvent.isExiting());
1064 EXPECT_EQ(x, dragEvent.getX());
1065 EXPECT_EQ(y, dragEvent.getY());
1066 }
1067
Antonio Kantekf16f2832021-09-28 04:39:20 +00001068 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001069 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 ASSERT_NE(nullptr, event) << mName.c_str()
1071 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001072 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1073 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001074
1075 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1076 << mName.c_str() << ": event displayId should always be NONE.";
1077 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1078 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1079 }
1080
chaviwd1c23182019-12-20 18:44:56 -08001081 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001082 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001083 if (event == nullptr) {
1084 return;
1085 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001086 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001087 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1088 ADD_FAILURE() << "Received key event "
1089 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001090 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001091 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1092 ADD_FAILURE() << "Received motion event "
1093 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001094 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1096 ADD_FAILURE() << "Received focus event, hasFocus = "
1097 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001098 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001099 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1100 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1101 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001102 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001103 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1104 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1105 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001106 }
1107 FAIL() << mName.c_str()
1108 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001109 }
1110
1111 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1112
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001113 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1114
chaviwd1c23182019-12-20 18:44:56 -08001115protected:
1116 std::unique_ptr<InputConsumer> mConsumer;
1117 PreallocatedInputEventFactory mEventFactory;
1118
1119 std::string mName;
1120};
1121
chaviw3277faf2021-05-19 16:45:23 -05001122class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001123public:
1124 static const int32_t WIDTH = 600;
1125 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001126
Chris Yea209fde2020-07-22 13:54:51 -07001127 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001128 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001130 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001131 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001132 base::Result<std::unique_ptr<InputChannel>> channel =
1133 dispatcher->createInputChannel(name);
1134 token = (*channel)->getConnectionToken();
1135 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001136 }
1137
1138 inputApplicationHandle->updateInfo();
1139 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1140
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001141 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001142 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001143 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001145 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001146 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001147 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001148 mInfo.globalScaleFactor = 1.0;
1149 mInfo.touchableRegion.clear();
1150 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001151 mInfo.ownerPid = WINDOW_PID;
1152 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001153 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001154 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001155 }
1156
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001157 sp<FakeWindowHandle> clone(int32_t displayId) {
1158 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1159 handle->mInfo = mInfo;
1160 handle->mInfo.displayId = displayId;
1161 handle->mInfo.id = sId++;
1162 handle->mInputReceiver = mInputReceiver;
1163 return handle;
1164 }
1165
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001166 void setTouchable(bool touchable) {
1167 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1168 }
chaviwd1c23182019-12-20 18:44:56 -08001169
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 void setFocusable(bool focusable) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1172 }
1173
1174 void setVisible(bool visible) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1176 }
Vishnu Nair958da932020-08-21 17:12:37 -07001177
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001178 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001179 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001180 }
1181
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001182 void setPaused(bool paused) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1184 }
1185
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001186 void setPreventSplitting(bool preventSplitting) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001188 }
1189
1190 void setSlippery(bool slippery) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1192 }
1193
1194 void setWatchOutsideTouch(bool watchOutside) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1196 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001197
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001198 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1199
1200 void setInterceptsStylus(bool interceptsStylus) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1202 }
1203
1204 void setDropInput(bool dropInput) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1206 }
1207
1208 void setDropInputIfObscured(bool dropInputIfObscured) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1210 }
1211
1212 void setNoInputChannel(bool noInputChannel) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1214 }
1215
Josep del Riob3981622023-04-18 15:49:45 +00001216 void setDisableUserActivity(bool disableUserActivity) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1218 }
1219
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001220 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1221
chaviw3277faf2021-05-19 16:45:23 -05001222 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001223
Bernardo Rufino7393d172021-02-26 13:56:11 +00001224 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1225
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001226 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001227 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001228 mInfo.touchableRegion.clear();
1229 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001230
1231 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1232 ui::Transform translate;
1233 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1234 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001235 }
1236
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001237 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1238
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001239 void setIsWallpaper(bool isWallpaper) {
1240 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1241 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001242
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001243 void setDupTouchToWallpaper(bool hasWallpaper) {
1244 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1245 }
chaviwd1c23182019-12-20 18:44:56 -08001246
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001247 void setTrustedOverlay(bool trustedOverlay) {
1248 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1249 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001250
chaviw9eaa22c2020-07-01 16:21:27 -07001251 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1252 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1253 }
1254
1255 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001256
yunho.shinf4a80b82020-11-16 21:13:57 +09001257 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1258
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001259 KeyEvent* consumeKey() {
1260 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1261 if (event == nullptr) {
1262 ADD_FAILURE() << "Consume failed : no event";
1263 return nullptr;
1264 }
1265 if (event->getType() != InputEventType::KEY) {
1266 ADD_FAILURE() << "Instead of key event, got " << *event;
1267 return nullptr;
1268 }
1269 return static_cast<KeyEvent*>(event);
1270 }
1271
1272 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1273 KeyEvent* keyEvent = consumeKey();
1274 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1275 ASSERT_THAT(*keyEvent, matcher);
1276 }
1277
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001278 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 }
1281
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001282 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001283 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001284 }
1285
Svet Ganov5d3bc372020-01-26 23:11:07 -08001286 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001287 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001288 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1289 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001290 }
1291
1292 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001294 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1295 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001296 }
1297
1298 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001299 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001300 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1301 }
1302
1303 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1304 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001305 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001306 expectedFlags);
1307 }
1308
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001310 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1311 int32_t expectedFlags = 0) {
1312 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1313 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001314 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001315 }
1316
1317 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001318 int32_t expectedFlags = 0) {
1319 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1320 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001321 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001322 }
1323
1324 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001325 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001327 expectedFlags);
1328 }
1329
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001330 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1331 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001332 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001333 expectedFlags);
1334 }
1335
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001336 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1337 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001338 MotionEvent* motionEvent = consumeMotion();
1339 ASSERT_NE(nullptr, motionEvent);
1340 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1341 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1342 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001343 }
1344
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001345 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1346 ASSERT_NE(mInputReceiver, nullptr)
1347 << "Cannot consume events from a window with no receiver";
1348 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1349 }
1350
Prabir Pradhan99987712020-11-10 18:43:05 -08001351 void consumeCaptureEvent(bool hasCapture) {
1352 ASSERT_NE(mInputReceiver, nullptr)
1353 << "Cannot consume events from a window with no receiver";
1354 mInputReceiver->consumeCaptureEvent(hasCapture);
1355 }
1356
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001357 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1358 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001359 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001360 ASSERT_THAT(*motionEvent, matcher);
1361 }
1362
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001363 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001364 std::optional<int32_t> expectedDisplayId,
1365 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001366 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1367 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1368 expectedFlags);
1369 }
1370
arthurhungb89ccb02020-12-30 16:19:01 +08001371 void consumeDragEvent(bool isExiting, float x, float y) {
1372 mInputReceiver->consumeDragEvent(isExiting, x, y);
1373 }
1374
Antonio Kantekf16f2832021-09-28 04:39:20 +00001375 void consumeTouchModeEvent(bool inTouchMode) {
1376 ASSERT_NE(mInputReceiver, nullptr)
1377 << "Cannot consume events from a window with no receiver";
1378 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1379 }
1380
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001381 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001382 if (mInputReceiver == nullptr) {
1383 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1384 return std::nullopt;
1385 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001386 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001387 }
1388
1389 void finishEvent(uint32_t sequenceNum) {
1390 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1391 mInputReceiver->finishEvent(sequenceNum);
1392 }
1393
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001394 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1395 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1396 mInputReceiver->sendTimeline(inputEventId, timeline);
1397 }
1398
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001399 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001400 if (mInputReceiver == nullptr) {
1401 return nullptr;
1402 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001403 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001404 }
1405
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001406 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001407 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001408 if (event == nullptr) {
1409 ADD_FAILURE() << "Consume failed : no event";
1410 return nullptr;
1411 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001412 if (event->getType() != InputEventType::MOTION) {
1413 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001414 return nullptr;
1415 }
1416 return static_cast<MotionEvent*>(event);
1417 }
1418
Arthur Hungb92218b2018-08-14 12:00:21 +08001419 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001420 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001421 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001422 return; // Can't receive events if the window does not have input channel
1423 }
1424 ASSERT_NE(nullptr, mInputReceiver)
1425 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001426 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001427 }
1428
chaviwaf87b3e2019-10-01 16:59:28 -07001429 sp<IBinder> getToken() { return mInfo.token; }
1430
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001431 const std::string& getName() { return mName; }
1432
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001433 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001434 mInfo.ownerPid = ownerPid;
1435 mInfo.ownerUid = ownerUid;
1436 }
1437
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001438 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001439
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001440 void destroyReceiver() { mInputReceiver = nullptr; }
1441
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001442 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1443
chaviwd1c23182019-12-20 18:44:56 -08001444private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001445 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001446 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001447 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001448 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001449 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001450};
1451
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001452std::atomic<int32_t> FakeWindowHandle::sId{1};
1453
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001454class FakeMonitorReceiver {
1455public:
1456 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
1457 int32_t displayId) {
1458 base::Result<std::unique_ptr<InputChannel>> channel =
1459 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
1460 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1461 }
1462
1463 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1464
1465 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1466 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1467 expectedFlags);
1468 }
1469
1470 std::optional<int32_t> receiveEvent() {
1471 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1472 }
1473
1474 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1475
1476 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1477 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1478 expectedDisplayId, expectedFlags);
1479 }
1480
1481 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1482 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1483 expectedDisplayId, expectedFlags);
1484 }
1485
1486 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1487 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1488 expectedDisplayId, expectedFlags);
1489 }
1490
1491 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1492 mInputReceiver->consumeMotionEvent(
1493 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1494 WithDisplayId(expectedDisplayId),
1495 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1496 }
1497
1498 void consumeMotionPointerDown(int32_t pointerIdx) {
1499 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1500 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1501 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1502 /*expectedFlags=*/0);
1503 }
1504
1505 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1506 mInputReceiver->consumeMotionEvent(matcher);
1507 }
1508
1509 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1510
1511 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1512
1513private:
1514 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1515};
1516
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001517static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519 int32_t displayId = ADISPLAY_ID_NONE,
1520 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001521 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001522 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001523 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001524 KeyEvent event;
1525 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1526
1527 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001528 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001529 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1530 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001531
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001532 if (!allowKeyRepeat) {
1533 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1534 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001535 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001536 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001537}
1538
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001539static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1540 InputEventInjectionResult result =
1541 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1542 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1543 if (result != InputEventInjectionResult::TIMED_OUT) {
1544 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1545 }
1546}
1547
1548static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001549 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001550 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001551}
1552
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001553// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1554// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1555// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001556static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1557 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001558 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001559 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001560 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001561}
1562
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001563static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001564 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001565 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001566}
1567
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001568static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001569 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001570 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001571 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001572 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001573 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1574 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001575}
1576
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001577static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001578 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1579 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001580 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001581 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1582 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001583 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001584 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001585 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001586 MotionEventBuilder motionBuilder =
1587 MotionEventBuilder(action, source)
1588 .displayId(displayId)
1589 .eventTime(eventTime)
1590 .rawXCursorPosition(cursorPosition.x)
1591 .rawYCursorPosition(cursorPosition.y)
1592 .pointer(
1593 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1594 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1595 motionBuilder.downTime(eventTime);
1596 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001597
1598 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001599 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1600 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001601}
1602
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001603static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1604 int32_t displayId,
1605 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001606 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001607}
1608
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001609static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1610 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001611 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001612 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001613}
1614
Jackal Guof9696682018-10-05 12:23:23 +08001615static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1616 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1617 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001618 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001619 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1620 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001621
1622 return args;
1623}
1624
Josep del Riob3981622023-04-18 15:49:45 +00001625static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1626 int32_t displayId = ADISPLAY_ID_NONE) {
1627 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1628 // Define a valid key event.
1629 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001630 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001631 currentTime);
1632
1633 return args;
1634}
1635
1636static NotifyKeyArgs generateAssistantKeyArgs(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_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001642 AMETA_NONE, currentTime);
1643
1644 return args;
1645}
1646
Prabir Pradhan678438e2023-04-13 19:32:51 +00001647[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1648 int32_t displayId,
1649 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001650 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001651 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1652 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1653 }
1654
chaviwd1c23182019-12-20 18:44:56 -08001655 PointerProperties pointerProperties[pointerCount];
1656 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001657
chaviwd1c23182019-12-20 18:44:56 -08001658 for (size_t i = 0; i < pointerCount; i++) {
1659 pointerProperties[i].clear();
1660 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001661 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001662
chaviwd1c23182019-12-20 18:44:56 -08001663 pointerCoords[i].clear();
1664 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1665 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1666 }
Jackal Guof9696682018-10-05 12:23:23 +08001667
1668 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1669 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001670 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001671 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1672 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001673 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001674 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001675 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001676 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001677
1678 return args;
1679}
1680
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001681static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1682 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1683}
1684
chaviwd1c23182019-12-20 18:44:56 -08001685static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1686 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1687}
1688
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001689static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1690 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001691 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001692}
1693
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001694} // namespace
1695
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001696/**
1697 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1698 * broken channel.
1699 */
1700TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1702 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001703 sp<FakeWindowHandle>::make(application, mDispatcher,
1704 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001705
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001706 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001707
1708 // Window closes its channel, but the window remains.
1709 window->destroyReceiver();
1710 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1711}
1712
Arthur Hungb92218b2018-08-14 12:00:21 +08001713TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001715 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1716 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001722
1723 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001724 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001725}
1726
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001727TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001729 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1730 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001731
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001732 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001733 // Inject a MotionEvent to an unknown display.
1734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001735 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1737
1738 // Window should receive motion event.
1739 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1740}
1741
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001742/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001743 * Calling onWindowInfosChanged once should not cause any issues.
1744 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001745 * called twice.
1746 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001747TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1750 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001751 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001752
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001755 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001756 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001757 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001758
1759 // Window should receive motion event.
1760 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1761}
1762
1763/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001764 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001765 */
1766TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001768 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1769 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001770 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001771
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001772 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1773 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001776 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001778
1779 // Window should receive motion event.
1780 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1781}
1782
Arthur Hungb92218b2018-08-14 12:00:21 +08001783// The foreground window should receive the first touch down event.
1784TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001786 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001787 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001788 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001789 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001790
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged(
1792 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001794 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001796
1797 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001798 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001799 windowSecond->assertNoEvents();
1800}
1801
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001802/**
1803 * Two windows: A top window, and a wallpaper behind the window.
1804 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1805 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001806 * 1. foregroundWindow <-- dup touch to wallpaper
1807 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001808 */
1809TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1811 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001812 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001813 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001814 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001815 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001816 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001817
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001818 mDispatcher->onWindowInfosChanged(
1819 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001821 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001822 {100, 200}))
1823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1824
1825 // Both foreground window and its wallpaper should receive the touch down
1826 foregroundWindow->consumeMotionDown();
1827 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1828
1829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001830 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001831 ADISPLAY_ID_DEFAULT, {110, 200}))
1832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1833
1834 foregroundWindow->consumeMotionMove();
1835 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1836
1837 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001838 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001839 foregroundWindow->consumeMotionCancel();
1840 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1841 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1842}
1843
1844/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001845 * Two fingers down on the window, and lift off the first finger.
1846 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1847 * contains a single pointer.
1848 */
1849TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1851 sp<FakeWindowHandle> window =
1852 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001854 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001855 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1857 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1858 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001859 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001860 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1861 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1862 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1863 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001864 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001865 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1866 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1867 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1868 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001869 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1870 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1871 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1872
1873 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001874 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001875 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1876 window->consumeMotionEvent(
1877 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1878}
1879
1880/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001881 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1882 * with the following differences:
1883 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1884 * clean up the connection.
1885 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1886 * Ensure that there's no crash in the dispatcher.
1887 */
1888TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1890 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001891 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001892 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001893 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001894 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001895 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001896
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001897 mDispatcher->onWindowInfosChanged(
1898 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001900 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001901 {100, 200}))
1902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1903
1904 // Both foreground window and its wallpaper should receive the touch down
1905 foregroundWindow->consumeMotionDown();
1906 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1907
1908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001909 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001910 ADISPLAY_ID_DEFAULT, {110, 200}))
1911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1912
1913 foregroundWindow->consumeMotionMove();
1914 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1915
1916 // Wallpaper closes its channel, but the window remains.
1917 wallpaperWindow->destroyReceiver();
1918 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1919
1920 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1921 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001922 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001923 foregroundWindow->consumeMotionCancel();
1924}
1925
Arthur Hungc539dbb2022-12-08 07:45:36 +00001926class ShouldSplitTouchFixture : public InputDispatcherTest,
1927 public ::testing::WithParamInterface<bool> {};
1928INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1929 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001930/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001931 * A single window that receives touch (on top), and a wallpaper window underneath it.
1932 * The top window gets a multitouch gesture.
1933 * Ensure that wallpaper gets the same gesture.
1934 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001935TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001937 sp<FakeWindowHandle> foregroundWindow =
1938 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1939 foregroundWindow->setDupTouchToWallpaper(true);
1940 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941
1942 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001943 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001944 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001945
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001946 mDispatcher->onWindowInfosChanged(
1947 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948
1949 // Touch down on top window
1950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001951 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952 {100, 100}))
1953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1954
1955 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001956 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1958
1959 // Second finger down on the top window
1960 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001961 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001963 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1964 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 .build();
1966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001967 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968 InputEventInjectionSync::WAIT_FOR_RESULT))
1969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1970
Harry Cutts33476232023-01-30 19:57:29 +00001971 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1972 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001973 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001974
1975 const MotionEvent secondFingerUpEvent =
1976 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1977 .displayId(ADISPLAY_ID_DEFAULT)
1978 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001979 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1980 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001981 .build();
1982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001983 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001984 InputEventInjectionSync::WAIT_FOR_RESULT))
1985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1986 foregroundWindow->consumeMotionPointerUp(0);
1987 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1988
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001990 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001991 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1992 AINPUT_SOURCE_TOUCHSCREEN)
1993 .displayId(ADISPLAY_ID_DEFAULT)
1994 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001995 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001996 .x(100)
1997 .y(100))
1998 .build(),
1999 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2001 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2002 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003}
2004
2005/**
2006 * Two windows: a window on the left and window on the right.
2007 * A third window, wallpaper, is behind both windows, and spans both top windows.
2008 * The first touch down goes to the left window. A second pointer touches down on the right window.
2009 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2010 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2011 * ACTION_POINTER_DOWN(1).
2012 */
2013TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2014 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2015 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002016 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002018 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002019
2020 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002021 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002022 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002023 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002024
2025 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002026 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002028 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002029
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002030 mDispatcher->onWindowInfosChanged(
2031 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2032 {},
2033 0,
2034 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035
2036 // Touch down on left window
2037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002039 {100, 100}))
2040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2041
2042 // Both foreground window and its wallpaper should receive the touch down
2043 leftWindow->consumeMotionDown();
2044 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2045
2046 // Second finger down on the right window
2047 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002048 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002050 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2051 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002052 .build();
2053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002054 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002055 InputEventInjectionSync::WAIT_FOR_RESULT))
2056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2057
2058 leftWindow->consumeMotionMove();
2059 // Since the touch is split, right window gets ACTION_DOWN
2060 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002061 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002062 expectedWallpaperFlags);
2063
2064 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002065 mDispatcher->onWindowInfosChanged(
2066 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002067 leftWindow->consumeMotionCancel();
2068 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2069 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2070
2071 // The pointer that's still down on the right window moves, and goes to the right window only.
2072 // As far as the dispatcher's concerned though, both pointers are still present.
2073 const MotionEvent secondFingerMoveEvent =
2074 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2075 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002076 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2077 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078 .build();
2079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002080 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002081 InputEventInjectionSync::WAIT_FOR_RESULT));
2082 rightWindow->consumeMotionMove();
2083
2084 leftWindow->assertNoEvents();
2085 rightWindow->assertNoEvents();
2086 wallpaperWindow->assertNoEvents();
2087}
2088
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089/**
2090 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2091 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2092 * The right window should receive ACTION_DOWN.
2093 */
2094TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002096 sp<FakeWindowHandle> leftWindow =
2097 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2098 leftWindow->setFrame(Rect(0, 0, 200, 200));
2099 leftWindow->setDupTouchToWallpaper(true);
2100 leftWindow->setSlippery(true);
2101
2102 sp<FakeWindowHandle> rightWindow =
2103 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2104 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002105
2106 sp<FakeWindowHandle> wallpaperWindow =
2107 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2108 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002110 mDispatcher->onWindowInfosChanged(
2111 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2112 {},
2113 0,
2114 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002115
Arthur Hungc539dbb2022-12-08 07:45:36 +00002116 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002119 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002121
2122 // Both foreground window and its wallpaper should receive the touch down
2123 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002124 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2125
Arthur Hungc539dbb2022-12-08 07:45:36 +00002126 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002128 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002129 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2131
Arthur Hungc539dbb2022-12-08 07:45:36 +00002132 leftWindow->consumeMotionCancel();
2133 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2134 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002135}
2136
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002137/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002138 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2139 * interactive, it might stop sending this flag.
2140 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2141 * to have a consistent input stream.
2142 *
2143 * Test procedure:
2144 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2145 * DOWN (new gesture).
2146 *
2147 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2148 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2149 *
2150 * We technically just need a single window here, but we are using two windows (spy on top and a
2151 * regular window below) to emulate the actual situation where it happens on the device.
2152 */
2153TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2155 sp<FakeWindowHandle> spyWindow =
2156 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2157 spyWindow->setFrame(Rect(0, 0, 200, 200));
2158 spyWindow->setTrustedOverlay(true);
2159 spyWindow->setSpy(true);
2160
2161 sp<FakeWindowHandle> window =
2162 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2163 window->setFrame(Rect(0, 0, 200, 200));
2164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002165 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002166 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002167
2168 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002169 mDispatcher->notifyMotion(
2170 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2171 .deviceId(touchDeviceId)
2172 .policyFlags(DEFAULT_POLICY_FLAGS)
2173 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2174 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002175
Prabir Pradhan678438e2023-04-13 19:32:51 +00002176 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2177 .deviceId(touchDeviceId)
2178 .policyFlags(DEFAULT_POLICY_FLAGS)
2179 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2180 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2181 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002182 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2183 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2184 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2185 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2186
2187 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002188 mDispatcher->notifyMotion(
2189 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2190 .deviceId(touchDeviceId)
2191 .policyFlags(0)
2192 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2193 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2194 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002195 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2196 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2197
2198 // We don't need to reset the device to reproduce the issue, but the reset event typically
2199 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002200 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002201
2202 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002203 mDispatcher->notifyMotion(
2204 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2205 .deviceId(touchDeviceId)
2206 .policyFlags(DEFAULT_POLICY_FLAGS)
2207 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2208 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002209 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2210 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2211
2212 // No more events
2213 spyWindow->assertNoEvents();
2214 window->assertNoEvents();
2215}
2216
2217/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002218 * Two windows: a window on the left and a window on the right.
2219 * Mouse is hovered from the right window into the left window.
2220 * Next, we tap on the left window, where the cursor was last seen.
2221 * The second tap is done onto the right window.
2222 * The mouse and tap are from two different devices.
2223 * We technically don't need to set the downtime / eventtime for these events, but setting these
2224 * explicitly helps during debugging.
2225 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2226 * In the buggy implementation, a tap on the right window would cause a crash.
2227 */
2228TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2230 sp<FakeWindowHandle> leftWindow =
2231 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2232 leftWindow->setFrame(Rect(0, 0, 200, 200));
2233
2234 sp<FakeWindowHandle> rightWindow =
2235 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2236 rightWindow->setFrame(Rect(200, 0, 400, 200));
2237
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002238 mDispatcher->onWindowInfosChanged(
2239 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2241 // stale.
2242 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2243 const int32_t mouseDeviceId = 6;
2244 const int32_t touchDeviceId = 4;
2245 // Move the cursor from right
2246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2249 AINPUT_SOURCE_MOUSE)
2250 .deviceId(mouseDeviceId)
2251 .downTime(baseTime + 10)
2252 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002254 .build()));
2255 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2256
2257 // .. to the left window
2258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002259 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002260 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2261 AINPUT_SOURCE_MOUSE)
2262 .deviceId(mouseDeviceId)
2263 .downTime(baseTime + 10)
2264 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002265 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002266 .build()));
2267 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2268 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2269 // Now tap the left window
2270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002271 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002272 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2273 AINPUT_SOURCE_TOUCHSCREEN)
2274 .deviceId(touchDeviceId)
2275 .downTime(baseTime + 40)
2276 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002277 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002278 .build()));
2279 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2280 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2281
2282 // release tap
2283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002284 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002285 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2286 AINPUT_SOURCE_TOUCHSCREEN)
2287 .deviceId(touchDeviceId)
2288 .downTime(baseTime + 40)
2289 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002290 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002291 .build()));
2292 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2293
2294 // Tap the window on the right
2295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002296 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002297 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2298 AINPUT_SOURCE_TOUCHSCREEN)
2299 .deviceId(touchDeviceId)
2300 .downTime(baseTime + 60)
2301 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002302 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002303 .build()));
2304 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2305
2306 // release tap
2307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002309 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2310 AINPUT_SOURCE_TOUCHSCREEN)
2311 .deviceId(touchDeviceId)
2312 .downTime(baseTime + 60)
2313 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002314 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002315 .build()));
2316 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2317
2318 // No more events
2319 leftWindow->assertNoEvents();
2320 rightWindow->assertNoEvents();
2321}
2322
2323/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002324 * Start hovering in a window. While this hover is still active, make another window appear on top.
2325 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2326 * While the top window is present, the hovering is stopped.
2327 * Later, hovering gets resumed again.
2328 * Ensure that new hover gesture is handled correctly.
2329 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2330 * to the window that's currently being hovered over.
2331 */
2332TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2334 sp<FakeWindowHandle> window =
2335 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2336 window->setFrame(Rect(0, 0, 200, 200));
2337
2338 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002339 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002340
2341 // Start hovering in the window
2342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2343 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2344 .build());
2345 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2346
2347 // Now, an obscuring window appears!
2348 sp<FakeWindowHandle> obscuringWindow =
2349 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2350 ADISPLAY_ID_DEFAULT,
2351 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2352 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2353 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2354 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2355 obscuringWindow->setNoInputChannel(true);
2356 obscuringWindow->setFocusable(false);
2357 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002358 mDispatcher->onWindowInfosChanged(
2359 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002360
2361 // While this new obscuring window is present, the hovering is stopped
2362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2363 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2364 .build());
2365 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2366
2367 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002369
2370 // And a new hover gesture starts.
2371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2372 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2373 .build());
2374 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2375}
2376
2377/**
2378 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2379 * the obscuring window.
2380 */
2381TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2383 sp<FakeWindowHandle> window =
2384 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2385 window->setFrame(Rect(0, 0, 200, 200));
2386
2387 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002388 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002389
2390 // Start hovering in the window
2391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2392 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2393 .build());
2394 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2395
2396 // Now, an obscuring window appears!
2397 sp<FakeWindowHandle> obscuringWindow =
2398 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2399 ADISPLAY_ID_DEFAULT,
2400 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2401 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2402 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2403 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2404 obscuringWindow->setNoInputChannel(true);
2405 obscuringWindow->setFocusable(false);
2406 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002407 mDispatcher->onWindowInfosChanged(
2408 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002409
2410 // While this new obscuring window is present, the hovering continues. The event can't go to the
2411 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2413 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2414 .build());
2415 obscuringWindow->assertNoEvents();
2416 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2417
2418 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002419 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002420
2421 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2422 // so it should generate a HOVER_ENTER
2423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2424 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2425 .build());
2426 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2427
2428 // Now the MOVE should be getting dispatched normally
2429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2430 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2431 .build());
2432 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2433}
2434
2435/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002436 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2437 * events are delivered to the window.
2438 */
2439TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2441 sp<FakeWindowHandle> window =
2442 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2443 window->setFrame(Rect(0, 0, 200, 200));
2444 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2445
2446 // Start hovering in the window
2447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2449 .build());
2450 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2451
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2453 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2456
2457 // Scroll with the mouse
2458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2459 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2460 .build());
2461 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2462}
2463
2464using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2465
2466/**
2467 * One window. Stylus down on the window. Next, touch from another device goes down.
2468 */
2469TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2471 sp<FakeWindowHandle> window =
2472 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2473 window->setFrame(Rect(0, 0, 200, 200));
2474
2475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2476
2477 constexpr int32_t touchDeviceId = 4;
2478 constexpr int32_t stylusDeviceId = 2;
2479
2480 // Stylus down
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2482 .deviceId(stylusDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2486
2487 // Touch down
2488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2491 .build());
2492 // Touch cancels stylus
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2494 WithCoords(100, 110)));
2495 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2496 WithCoords(140, 145)));
2497
2498 // Touch move
2499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2500 .deviceId(touchDeviceId)
2501 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2502 .build());
2503 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2504 WithCoords(141, 146)));
2505
2506 // Subsequent stylus movements are dropped
2507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2508 .deviceId(stylusDeviceId)
2509 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2510 .build());
2511 window->assertNoEvents();
2512}
2513
2514/**
2515 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2516 * down.
2517 * Similar test as above, but with added SPY window.
2518 */
2519TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2521 sp<FakeWindowHandle> window =
2522 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2523 sp<FakeWindowHandle> spyWindow =
2524 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2525 spyWindow->setFrame(Rect(0, 0, 200, 200));
2526 spyWindow->setTrustedOverlay(true);
2527 spyWindow->setSpy(true);
2528 window->setFrame(Rect(0, 0, 200, 200));
2529
2530 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2531
2532 constexpr int32_t touchDeviceId = 4;
2533 constexpr int32_t stylusDeviceId = 2;
2534
2535 // Stylus down
2536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2537 .deviceId(stylusDeviceId)
2538 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2539 .build());
2540 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2541 spyWindow->consumeMotionEvent(
2542 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2543
2544 // Touch down
2545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2546 .deviceId(touchDeviceId)
2547 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2548 .build());
2549
2550 // Touch move
2551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2552 .deviceId(touchDeviceId)
2553 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2554 .build());
2555 window->consumeMotionEvent(
2556 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2557 spyWindow->consumeMotionEvent(
2558 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2559 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2560 spyWindow->consumeMotionEvent(
2561 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2562 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2563 spyWindow->consumeMotionEvent(
2564 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2565 // Subsequent stylus movements are dropped
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2567 .deviceId(stylusDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2569 .build());
2570
2571 window->assertNoEvents();
2572 spyWindow->assertNoEvents();
2573}
2574
2575/**
2576 * One window. Stylus hover on the window. Next, touch from another device goes down.
2577 */
2578TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2580 sp<FakeWindowHandle> window =
2581 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2582 window->setFrame(Rect(0, 0, 200, 200));
2583
2584 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2585
2586 constexpr int32_t touchDeviceId = 4;
2587 constexpr int32_t stylusDeviceId = 2;
2588
2589 // Stylus down on the window
2590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2591 .deviceId(stylusDeviceId)
2592 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2593 .build());
2594 window->consumeMotionEvent(
2595 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2596
2597 // Touch down on window
2598 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2599 .deviceId(touchDeviceId)
2600 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2601 .build());
2602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2603 .deviceId(touchDeviceId)
2604 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2605 .build());
2606 window->consumeMotionEvent(
2607 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2608 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2609 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2610 // Subsequent stylus movements are ignored
2611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2612 .deviceId(stylusDeviceId)
2613 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2614 .build());
2615 window->assertNoEvents();
2616}
2617
2618/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002619 * Two windows: a window on the left and a window on the right.
2620 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2621 * down. Then, on the left window, also place second touch pointer down.
2622 * This test tries to reproduce a crash.
2623 * In the buggy implementation, second pointer down on the left window would cause a crash.
2624 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002625TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2627 sp<FakeWindowHandle> leftWindow =
2628 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2629 leftWindow->setFrame(Rect(0, 0, 200, 200));
2630
2631 sp<FakeWindowHandle> rightWindow =
2632 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2633 rightWindow->setFrame(Rect(200, 0, 400, 200));
2634
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002635 mDispatcher->onWindowInfosChanged(
2636 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002637
2638 const int32_t touchDeviceId = 4;
2639 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002640
2641 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2643 .deviceId(mouseDeviceId)
2644 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2645 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002646 leftWindow->consumeMotionEvent(
2647 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2648
2649 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2651 .deviceId(mouseDeviceId)
2652 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2653 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2654 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002655
2656 leftWindow->consumeMotionEvent(
2657 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2658 leftWindow->consumeMotionEvent(
2659 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2660
Prabir Pradhan678438e2023-04-13 19:32:51 +00002661 mDispatcher->notifyMotion(
2662 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2663 .deviceId(mouseDeviceId)
2664 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2665 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002668 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2669
2670 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2672 .deviceId(touchDeviceId)
2673 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2674 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002675 leftWindow->consumeMotionEvent(
2676 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002677 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2678
2679 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002680 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2681 .deviceId(touchDeviceId)
2682 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2683 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2684 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002685 leftWindow->consumeMotionEvent(
2686 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2687 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2688 // current implementation.
2689 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2690 rightWindow->consumeMotionEvent(
2691 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2692
2693 leftWindow->assertNoEvents();
2694 rightWindow->assertNoEvents();
2695}
2696
2697/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002698 * Two windows: a window on the left and a window on the right.
2699 * Mouse is hovered on the left window and stylus is hovered on the right window.
2700 */
2701TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2703 sp<FakeWindowHandle> leftWindow =
2704 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2705 leftWindow->setFrame(Rect(0, 0, 200, 200));
2706
2707 sp<FakeWindowHandle> rightWindow =
2708 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2709 rightWindow->setFrame(Rect(200, 0, 400, 200));
2710
2711 mDispatcher->onWindowInfosChanged(
2712 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2713
2714 const int32_t stylusDeviceId = 3;
2715 const int32_t mouseDeviceId = 6;
2716
2717 // Start hovering over the left window
2718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2719 .deviceId(mouseDeviceId)
2720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2721 .build());
2722 leftWindow->consumeMotionEvent(
2723 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2724
2725 // Stylus hovered on right window
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2729 .build());
2730 leftWindow->consumeMotionEvent(
2731 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2732 rightWindow->consumeMotionEvent(
2733 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2734
2735 // Subsequent HOVER_MOVE events are dispatched correctly.
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2737 .deviceId(mouseDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2739 .build());
2740 leftWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2742 rightWindow->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2744
2745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2746 .deviceId(stylusDeviceId)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2748 .build());
2749 leftWindow->consumeMotionEvent(
2750 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2751 rightWindow->consumeMotionEvent(
2752 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2753
2754 leftWindow->assertNoEvents();
2755 rightWindow->assertNoEvents();
2756}
2757
2758/**
2759 * Three windows: a window on the left and a window on the right.
2760 * And a spy window that's positioned above all of them.
2761 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2762 * Check the stream that's received by the spy.
2763 */
2764TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2766
2767 sp<FakeWindowHandle> spyWindow =
2768 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2769 spyWindow->setFrame(Rect(0, 0, 400, 400));
2770 spyWindow->setTrustedOverlay(true);
2771 spyWindow->setSpy(true);
2772
2773 sp<FakeWindowHandle> leftWindow =
2774 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2775 leftWindow->setFrame(Rect(0, 0, 200, 200));
2776
2777 sp<FakeWindowHandle> rightWindow =
2778 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2779
2780 rightWindow->setFrame(Rect(200, 0, 400, 200));
2781
2782 mDispatcher->onWindowInfosChanged(
2783 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2784
2785 const int32_t stylusDeviceId = 1;
2786 const int32_t touchDeviceId = 2;
2787
2788 // Stylus down on the left window
2789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2790 .deviceId(stylusDeviceId)
2791 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2792 .build());
2793 leftWindow->consumeMotionEvent(
2794 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2795 spyWindow->consumeMotionEvent(
2796 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2797
2798 // Touch down on the right window
2799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2800 .deviceId(touchDeviceId)
2801 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2802 .build());
2803 leftWindow->consumeMotionEvent(
2804 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2805 spyWindow->consumeMotionEvent(
2806 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2807 rightWindow->consumeMotionEvent(
2808 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2809 spyWindow->consumeMotionEvent(
2810 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2811
2812 // Stylus movements continue, but are ignored because the touch went down more recently.
2813 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2814 .deviceId(stylusDeviceId)
2815 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2816 .build());
2817
2818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2819 .deviceId(touchDeviceId)
2820 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2821 .build());
2822 rightWindow->consumeMotionEvent(
2823 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2824 spyWindow->consumeMotionEvent(
2825 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2826
2827 spyWindow->assertNoEvents();
2828 leftWindow->assertNoEvents();
2829 rightWindow->assertNoEvents();
2830}
2831
2832/**
2833 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2834 * both.
2835 * Check hover in left window and touch down in the right window.
2836 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2837 */
2838TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2840
2841 sp<FakeWindowHandle> spyWindow =
2842 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2843 spyWindow->setFrame(Rect(0, 0, 400, 400));
2844 spyWindow->setTrustedOverlay(true);
2845 spyWindow->setSpy(true);
2846
2847 sp<FakeWindowHandle> leftWindow =
2848 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2849 leftWindow->setFrame(Rect(0, 0, 200, 200));
2850
2851 sp<FakeWindowHandle> rightWindow =
2852 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2853 rightWindow->setFrame(Rect(200, 0, 400, 200));
2854
2855 mDispatcher->onWindowInfosChanged(
2856 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2857
2858 const int32_t stylusDeviceId = 1;
2859 const int32_t touchDeviceId = 2;
2860
2861 // Stylus hover on the left window
2862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2863 .deviceId(stylusDeviceId)
2864 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2865 .build());
2866 leftWindow->consumeMotionEvent(
2867 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2868 spyWindow->consumeMotionEvent(
2869 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2870
2871 // Touch down on the right window.
2872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2873 .deviceId(touchDeviceId)
2874 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2875 .build());
2876 leftWindow->consumeMotionEvent(
2877 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2878 spyWindow->consumeMotionEvent(
2879 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2880 spyWindow->consumeMotionEvent(
2881 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2882 rightWindow->consumeMotionEvent(
2883 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2884
2885 // Stylus movements continue, but are ignored because the touch is down.
2886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2887 .deviceId(stylusDeviceId)
2888 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2889 .build());
2890
2891 // Touch movements continue. They should be delivered to the right window and to the spy
2892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2893 .deviceId(touchDeviceId)
2894 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2895 .build());
2896 spyWindow->consumeMotionEvent(
2897 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2898 rightWindow->consumeMotionEvent(
2899 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2900
2901 spyWindow->assertNoEvents();
2902 leftWindow->assertNoEvents();
2903 rightWindow->assertNoEvents();
2904}
2905
2906/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002907 * On a single window, use two different devices: mouse and touch.
2908 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2909 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2910 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2911 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2912 * represent a new gesture.
2913 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002914TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2916 sp<FakeWindowHandle> window =
2917 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2918 window->setFrame(Rect(0, 0, 400, 400));
2919
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002920 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002921
2922 const int32_t touchDeviceId = 4;
2923 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002924
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002925 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2927 .deviceId(touchDeviceId)
2928 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2929 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002930 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002931 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2932 .deviceId(touchDeviceId)
2933 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2934 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2935 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002936 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002937 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2938 .deviceId(touchDeviceId)
2939 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2940 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2941 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002942 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2943 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2944 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2945
2946 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2948 .deviceId(mouseDeviceId)
2949 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2951 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002952
2953 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002954 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002955 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2956
Prabir Pradhan678438e2023-04-13 19:32:51 +00002957 mDispatcher->notifyMotion(
2958 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2959 .deviceId(mouseDeviceId)
2960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2961 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2963 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002964 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2965
2966 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002967 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2971 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002972 // Since we already canceled this touch gesture, it will be ignored until a completely new
2973 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2974 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2975 // However, mouse movements should continue to work.
2976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2977 .deviceId(mouseDeviceId)
2978 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2979 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2980 .build());
2981 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2982
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002983 window->assertNoEvents();
2984}
2985
2986/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002987 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2988 * the injected event.
2989 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002990TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2992 sp<FakeWindowHandle> window =
2993 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2994 window->setFrame(Rect(0, 0, 400, 400));
2995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002996 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002997
2998 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002999 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3000 // completion.
3001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003002 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003003 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3004 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003005 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003006 .build()));
3007 window->consumeMotionEvent(
3008 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3009
3010 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3011 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003012 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3013 .deviceId(touchDeviceId)
3014 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3015 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003016
3017 window->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3019 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3020}
3021
3022/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003023 * This test is similar to the test above, but the sequence of injected events is different.
3024 *
3025 * Two windows: a window on the left and a window on the right.
3026 * Mouse is hovered over the left window.
3027 * Next, we tap on the left window, where the cursor was last seen.
3028 *
3029 * After that, we inject one finger down onto the right window, and then a second finger down onto
3030 * the left window.
3031 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3032 * window (first), and then another on the left window (second).
3033 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3034 * In the buggy implementation, second finger down on the left window would cause a crash.
3035 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003036TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3038 sp<FakeWindowHandle> leftWindow =
3039 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3040 leftWindow->setFrame(Rect(0, 0, 200, 200));
3041
3042 sp<FakeWindowHandle> rightWindow =
3043 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3044 rightWindow->setFrame(Rect(200, 0, 400, 200));
3045
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003046 mDispatcher->onWindowInfosChanged(
3047 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003048
3049 const int32_t mouseDeviceId = 6;
3050 const int32_t touchDeviceId = 4;
3051 // Hover over the left window. Keep the cursor there.
3052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003053 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003054 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3055 AINPUT_SOURCE_MOUSE)
3056 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003057 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003058 .build()));
3059 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3060
3061 // Tap on left window
3062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003063 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003064 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3065 AINPUT_SOURCE_TOUCHSCREEN)
3066 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003067 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003068 .build()));
3069
3070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003071 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003072 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3073 AINPUT_SOURCE_TOUCHSCREEN)
3074 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003075 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003076 .build()));
3077 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3078 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3079 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3080
3081 // First finger down on right window
3082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003083 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003084 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3085 AINPUT_SOURCE_TOUCHSCREEN)
3086 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003087 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003088 .build()));
3089 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3090
3091 // Second finger down on the left window
3092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003093 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003094 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3095 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003096 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3097 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003098 .build()));
3099 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3100 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3101
3102 // No more events
3103 leftWindow->assertNoEvents();
3104 rightWindow->assertNoEvents();
3105}
3106
3107/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003108 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3109 * While the touch is down, new hover events from the stylus device should be ignored. After the
3110 * touch is gone, stylus hovering should start working again.
3111 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003112TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3114 sp<FakeWindowHandle> window =
3115 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3116 window->setFrame(Rect(0, 0, 200, 200));
3117
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003118 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003119
3120 const int32_t stylusDeviceId = 5;
3121 const int32_t touchDeviceId = 4;
3122 // Start hovering with stylus
3123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003124 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003125 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003126 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003127 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003128 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003129 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003130
3131 // Finger down on the window
3132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003133 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003134 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003135 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003136 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003137 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003138 window->consumeMotionEvent(
3139 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3140 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003141
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003142 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003143 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003144 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003145 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3146 AINPUT_SOURCE_STYLUS)
3147 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003148 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003149 .build()));
3150 // No event should be sent. This event should be ignored because a pointer from another device
3151 // is already down.
3152
3153 // Lift up the finger
3154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003155 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003156 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3157 AINPUT_SOURCE_TOUCHSCREEN)
3158 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003159 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003160 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003161 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003162
3163 // Now that the touch is gone, stylus hovering should start working again
3164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003165 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003166 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3167 AINPUT_SOURCE_STYLUS)
3168 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003169 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003170 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003171 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3172 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003173 window->assertNoEvents();
3174}
3175
3176/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003177 * A spy window above a window with no input channel.
3178 * Start hovering with a stylus device, and then tap with it.
3179 * Ensure spy window receives the entire sequence.
3180 */
3181TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3182 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3183 sp<FakeWindowHandle> spyWindow =
3184 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3185 spyWindow->setFrame(Rect(0, 0, 200, 200));
3186 spyWindow->setTrustedOverlay(true);
3187 spyWindow->setSpy(true);
3188 sp<FakeWindowHandle> window =
3189 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3190 window->setNoInputChannel(true);
3191 window->setFrame(Rect(0, 0, 200, 200));
3192
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003193 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003194
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003195 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3197 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3198 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3200 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003201 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3202 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3203 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003204 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3205
3206 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, 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_DOWN));
3211
3212 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3214 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3215 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003216 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3217
3218 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3220 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3221 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003222 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3223 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003224 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, 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_HOVER_EXIT));
3228
3229 // No more events
3230 spyWindow->assertNoEvents();
3231 window->assertNoEvents();
3232}
3233
3234/**
3235 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3236 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3237 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3238 * While the mouse is down, new move events from the touch device should be ignored.
3239 */
3240TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3242 sp<FakeWindowHandle> spyWindow =
3243 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3244 spyWindow->setFrame(Rect(0, 0, 200, 200));
3245 spyWindow->setTrustedOverlay(true);
3246 spyWindow->setSpy(true);
3247 sp<FakeWindowHandle> window =
3248 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3249 window->setFrame(Rect(0, 0, 200, 200));
3250
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003251 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003252
3253 const int32_t mouseDeviceId = 7;
3254 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003255
3256 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3258 .deviceId(mouseDeviceId)
3259 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3260 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003261 spyWindow->consumeMotionEvent(
3262 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3263 window->consumeMotionEvent(
3264 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3265
3266 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3268 .deviceId(touchDeviceId)
3269 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3270 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003271 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3272 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3273 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3274 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3275
Prabir Pradhan678438e2023-04-13 19:32:51 +00003276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3277 .deviceId(touchDeviceId)
3278 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3279 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003280 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3281 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3282
3283 // Pilfer the stream
3284 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3285 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
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(60).y(60))
3290 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003291 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3292
3293 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3295 .deviceId(mouseDeviceId)
3296 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3297 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3298 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003299
3300 spyWindow->consumeMotionEvent(
3301 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3302 spyWindow->consumeMotionEvent(
3303 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3304 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3305
Prabir Pradhan678438e2023-04-13 19:32:51 +00003306 mDispatcher->notifyMotion(
3307 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3308 .deviceId(mouseDeviceId)
3309 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3310 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3311 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3312 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003313 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3314 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3315
3316 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003317 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3318 .deviceId(mouseDeviceId)
3319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3321 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003322 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3323 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3324
3325 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3327 .deviceId(touchDeviceId)
3328 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3329 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003330
3331 // No more events
3332 spyWindow->assertNoEvents();
3333 window->assertNoEvents();
3334}
3335
3336/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003337 * On the display, have a single window, and also an area where there's no window.
3338 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3339 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3340 */
3341TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003344 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003345
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003346 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003347
3348 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003349 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003350
3351 mDispatcher->waitForIdle();
3352 window->assertNoEvents();
3353
3354 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003355 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003356 mDispatcher->waitForIdle();
3357 window->consumeMotionDown();
3358}
3359
3360/**
3361 * Same test as above, but instead of touching the empty space, the first touch goes to
3362 * non-touchable window.
3363 */
3364TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3366 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003367 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003368 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3369 window1->setTouchable(false);
3370 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003371 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003372 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3373
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003374 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003375
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003376 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003377 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003378
3379 mDispatcher->waitForIdle();
3380 window1->assertNoEvents();
3381 window2->assertNoEvents();
3382
3383 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003384 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003385 mDispatcher->waitForIdle();
3386 window2->consumeMotionDown();
3387}
3388
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003389/**
3390 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3391 * to the event time of the first ACTION_DOWN sent to the particular window.
3392 */
3393TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3395 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003396 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003397 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3398 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003400 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003402 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003403
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003404 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003405 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003406
3407 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003408
3409 MotionEvent* motionEvent1 = window1->consumeMotion();
3410 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003411 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003412 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3413 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003414
3415 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003416 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003417 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003418 MotionEvent* motionEvent2 = window2->consumeMotion();
3419 ASSERT_NE(motionEvent2, nullptr);
3420 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003421 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003422 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003423
3424 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003425 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003426 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003427 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003428
3429 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003430 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003431 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003432 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003433
3434 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3435 window1->consumeMotionMove();
3436 window1->assertNoEvents();
3437
3438 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003439 mDispatcher->notifyMotion(
3440 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003441 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003442 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003443
Prabir Pradhan678438e2023-04-13 19:32:51 +00003444 mDispatcher->notifyMotion(
3445 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003446 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003447 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003448}
3449
Garfield Tandf26e862020-07-01 20:18:19 -07003450TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003452 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003453 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003454 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003455 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003456 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003457 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003458
3459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3460
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003461 mDispatcher->onWindowInfosChanged(
3462 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003463
3464 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003466 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003467 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3468 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003469 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003470 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003471 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003472
3473 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003475 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003476 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3477 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003479 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003480 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3481 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003482
3483 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003485 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003486 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3487 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003488 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003489 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003490 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3491 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003492
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003494 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003495 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3496 AINPUT_SOURCE_MOUSE)
3497 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3498 .actionButton(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 Vishniakou5cee1e32022-11-29 12:35:39 -08003501 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003502
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003504 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003505 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3506 AINPUT_SOURCE_MOUSE)
3507 .buttonState(0)
3508 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003509 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003510 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003511 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003514 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003515 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3516 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003517 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003518 .build()));
3519 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3520
3521 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003523 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003524 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3525 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003526 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003527 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003528 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003529
3530 // No more events
3531 windowLeft->assertNoEvents();
3532 windowRight->assertNoEvents();
3533}
3534
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003535/**
3536 * Put two fingers down (and don't release them) and click the mouse button.
3537 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3538 * currently active gesture should be canceled, and the new one should proceed.
3539 */
3540TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3542 sp<FakeWindowHandle> window =
3543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3544 window->setFrame(Rect(0, 0, 600, 800));
3545
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003546 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003547
3548 const int32_t touchDeviceId = 4;
3549 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003550
3551 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3553 .deviceId(touchDeviceId)
3554 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3555 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003556
Prabir Pradhan678438e2023-04-13 19:32:51 +00003557 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3558 .deviceId(touchDeviceId)
3559 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3560 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3561 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003562 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3563 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3564
3565 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3567 .deviceId(mouseDeviceId)
3568 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3569 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3570 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003571 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3572 WithPointerCount(2u)));
3573 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3574
Prabir Pradhan678438e2023-04-13 19:32:51 +00003575 mDispatcher->notifyMotion(
3576 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3577 .deviceId(mouseDeviceId)
3578 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3579 .actionButton(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(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3583
3584 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3585 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003586 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3587 .deviceId(touchDeviceId)
3588 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3589 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3590 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003591 window->assertNoEvents();
3592}
3593
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003594TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3596
3597 sp<FakeWindowHandle> spyWindow =
3598 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3599 spyWindow->setFrame(Rect(0, 0, 600, 800));
3600 spyWindow->setTrustedOverlay(true);
3601 spyWindow->setSpy(true);
3602 sp<FakeWindowHandle> window =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3604 window->setFrame(Rect(0, 0, 600, 800));
3605
3606 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003607 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003608
3609 // Send mouse cursor to the window
3610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003611 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003612 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3613 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003615 .build()));
3616
3617 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3618 WithSource(AINPUT_SOURCE_MOUSE)));
3619 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3620 WithSource(AINPUT_SOURCE_MOUSE)));
3621
3622 window->assertNoEvents();
3623 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003624}
3625
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003626TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3628
3629 sp<FakeWindowHandle> spyWindow =
3630 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3631 spyWindow->setFrame(Rect(0, 0, 600, 800));
3632 spyWindow->setTrustedOverlay(true);
3633 spyWindow->setSpy(true);
3634 sp<FakeWindowHandle> window =
3635 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3636 window->setFrame(Rect(0, 0, 600, 800));
3637
3638 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003639 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003640
3641 // Send mouse cursor to the window
3642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003643 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003644 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3645 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003646 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003647 .build()));
3648
3649 // Move mouse cursor
3650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003651 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003652 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3653 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003654 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003655 .build()));
3656
3657 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3658 WithSource(AINPUT_SOURCE_MOUSE)));
3659 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3660 WithSource(AINPUT_SOURCE_MOUSE)));
3661 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3662 WithSource(AINPUT_SOURCE_MOUSE)));
3663 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3664 WithSource(AINPUT_SOURCE_MOUSE)));
3665 // Touch down on the window
3666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003667 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003668 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3669 AINPUT_SOURCE_TOUCHSCREEN)
3670 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003671 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003672 .build()));
3673 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3674 WithSource(AINPUT_SOURCE_MOUSE)));
3675 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3676 WithSource(AINPUT_SOURCE_MOUSE)));
3677 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3678 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3679 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3680 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3681
3682 // pilfer the motion, retaining the gesture on the spy window.
3683 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3684 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3685 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3686
3687 // Touch UP on the window
3688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003689 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003690 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3691 AINPUT_SOURCE_TOUCHSCREEN)
3692 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003693 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003694 .build()));
3695 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3696 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3697
3698 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3699 // to send a new gesture. It should again go to both windows (spy and the window below), just
3700 // like the first gesture did, before pilfering. The window configuration has not changed.
3701
3702 // One more tap - DOWN
3703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003704 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003705 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3706 AINPUT_SOURCE_TOUCHSCREEN)
3707 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003708 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003709 .build()));
3710 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3711 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3712 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3713 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3714
3715 // Touch UP on the window
3716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003717 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003718 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3719 AINPUT_SOURCE_TOUCHSCREEN)
3720 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003721 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003722 .build()));
3723 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3724 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3725 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3726 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3727
3728 window->assertNoEvents();
3729 spyWindow->assertNoEvents();
3730}
3731
Garfield Tandf26e862020-07-01 20:18:19 -07003732// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3733// directly in this test.
3734TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003736 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003737 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003738 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003739
3740 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3741
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003742 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003743
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003745 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003746 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3747 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003748 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003749 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003750 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003751 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003753 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003754 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3755 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003756 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003757 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003758 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3759 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003760
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003762 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003763 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3764 AINPUT_SOURCE_MOUSE)
3765 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3766 .actionButton(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 Vishniakou5cee1e32022-11-29 12:35:39 -08003769 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003770
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003772 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003773 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3774 AINPUT_SOURCE_MOUSE)
3775 .buttonState(0)
3776 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003777 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003778 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003779 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003780
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003782 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003783 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3784 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003785 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003786 .build()));
3787 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3788
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003789 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3790 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3791 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003792 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003793 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3794 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003795 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003796 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003797 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003798}
3799
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003800/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003801 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3802 * is generated.
3803 */
3804TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3806 sp<FakeWindowHandle> window =
3807 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3808 window->setFrame(Rect(0, 0, 1200, 800));
3809
3810 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3811
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003812 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003813
3814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003815 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003816 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3817 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003818 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003819 .build()));
3820 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3821
3822 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003823 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003824 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3825}
3826
3827/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003828 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3829 */
3830TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3832 sp<FakeWindowHandle> window =
3833 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3834 window->setFrame(Rect(0, 0, 1200, 800));
3835
3836 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3837
3838 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3839
3840 MotionEventBuilder hoverEnterBuilder =
3841 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3842 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3843 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3845 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3847 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3848 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3849 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3850}
3851
3852/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003853 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3854 */
3855TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3857 sp<FakeWindowHandle> window =
3858 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3859 window->setFrame(Rect(0, 0, 100, 100));
3860
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003861 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003862
3863 const int32_t mouseDeviceId = 7;
3864 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003865
3866 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3868 .deviceId(mouseDeviceId)
3869 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3870 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003871 window->consumeMotionEvent(
3872 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3873
3874 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3876 .deviceId(touchDeviceId)
3877 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3878 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003879
3880 window->consumeMotionEvent(
3881 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3882 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3883}
3884
3885/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003886 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003887 * The tap causes a HOVER_EXIT event to be generated because the current event
3888 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003889 */
3890TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3892 sp<FakeWindowHandle> window =
3893 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3894 window->setFrame(Rect(0, 0, 100, 100));
3895
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3898 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3899 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003900 ASSERT_NO_FATAL_FAILURE(
3901 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3902 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003903
3904 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3907 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003908 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003909 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3910 WithSource(AINPUT_SOURCE_MOUSE))));
3911
3912 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003913 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3914 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3915
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, 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(
3920 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3921 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3922}
3923
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003924TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3926 sp<FakeWindowHandle> windowDefaultDisplay =
3927 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3928 ADISPLAY_ID_DEFAULT);
3929 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3930 sp<FakeWindowHandle> windowSecondDisplay =
3931 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3932 SECOND_DISPLAY_ID);
3933 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3934
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003935 mDispatcher->onWindowInfosChanged(
3936 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003937
3938 // Set cursor position in window in default display and check that hover enter and move
3939 // events are generated.
3940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003941 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003942 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3943 AINPUT_SOURCE_MOUSE)
3944 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003945 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003946 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003947 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003948
3949 // Remove all windows in secondary display and check that no event happens on window in
3950 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003951 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3952
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003953 windowDefaultDisplay->assertNoEvents();
3954
3955 // Move cursor position in window in default display and check that only hover move
3956 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003957 mDispatcher->onWindowInfosChanged(
3958 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003960 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003961 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3962 AINPUT_SOURCE_MOUSE)
3963 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003965 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003966 windowDefaultDisplay->consumeMotionEvent(
3967 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3968 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003969 windowDefaultDisplay->assertNoEvents();
3970}
3971
Garfield Tan00f511d2019-06-12 16:55:40 -07003972TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003974
3975 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003977 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003978 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003979 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003980 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003981
3982 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3983
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003984 mDispatcher->onWindowInfosChanged(
3985 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003986
3987 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3988 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003990 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003991 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003992 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003993 windowRight->assertNoEvents();
3994}
3995
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003996TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003998 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3999 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004000 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004001
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004002 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004003 setFocusedWindow(window);
4004
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004005 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004006
Prabir Pradhan678438e2023-04-13 19:32:51 +00004007 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004008
4009 // Window should receive key down event.
4010 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4011
4012 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4013 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004014 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004015 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004016 AKEY_EVENT_FLAG_CANCELED);
4017}
4018
4019TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004021 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4022 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004023
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004024 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004025
Prabir Pradhan678438e2023-04-13 19:32:51 +00004026 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4027 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004028
4029 // Window should receive motion down event.
4030 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4031
4032 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4033 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004034 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004035 window->consumeMotionEvent(
4036 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004037}
4038
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004039TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4041 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4042 "Fake Window", ADISPLAY_ID_DEFAULT);
4043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004044 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004045
4046 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4047 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4048 .build());
4049
4050 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4051
4052 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4053 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4054 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4055
4056 // After the device has been reset, a new hovering stream can be sent to the window
4057 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4058 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4059 .build());
4060 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4061}
4062
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004063TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004065 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4066 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004067 window->setFocusable(true);
4068
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004069 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004070 setFocusedWindow(window);
4071
4072 window->consumeFocusEvent(true);
4073
Prabir Pradhan678438e2023-04-13 19:32:51 +00004074 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004075 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4076 const nsecs_t injectTime = keyArgs.eventTime;
4077 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004078 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004079 // The dispatching time should be always greater than or equal to intercept key timeout.
4080 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4081 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4082 std::chrono::nanoseconds(interceptKeyTimeout).count());
4083}
4084
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004085/**
4086 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4087 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004088TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004090 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4091 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004092 window->setFocusable(true);
4093
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004094 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004095 setFocusedWindow(window);
4096
4097 window->consumeFocusEvent(true);
4098
Prabir Pradhan678438e2023-04-13 19:32:51 +00004099 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004100 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004101
4102 // Set a value that's significantly larger than the default consumption timeout. If the
4103 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4104 mFakePolicy->setInterceptKeyTimeout(600ms);
4105 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4106 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004107 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4108}
4109
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004110/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004111 * Two windows. First is a regular window. Second does not overlap with the first, and has
4112 * WATCH_OUTSIDE_TOUCH.
4113 * Both windows are owned by the same UID.
4114 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4115 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4116 */
4117TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004119 sp<FakeWindowHandle> window =
4120 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004121 window->setFrame(Rect{0, 0, 100, 100});
4122
4123 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004124 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004125 ADISPLAY_ID_DEFAULT);
4126 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4127 outsideWindow->setWatchOutsideTouch(true);
4128 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004129 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004130
4131 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004132 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4133 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4134 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004135 window->consumeMotionDown();
4136 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4137 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4138 outsideWindow->consumeMotionEvent(
4139 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4140}
4141
4142/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004143 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4144 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4145 * ACTION_OUTSIDE event is sent per gesture.
4146 */
4147TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4148 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004150 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4151 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004152 window->setWatchOutsideTouch(true);
4153 window->setFrame(Rect{0, 0, 100, 100});
4154 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004155 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4156 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004157 secondWindow->setFrame(Rect{100, 100, 200, 200});
4158 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004159 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4160 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004161 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004162 mDispatcher->onWindowInfosChanged(
4163 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004164
4165 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4167 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4168 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004169 window->assertNoEvents();
4170 secondWindow->assertNoEvents();
4171
4172 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4173 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004174 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4175 ADISPLAY_ID_DEFAULT,
4176 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004177 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4178 window->consumeMotionEvent(
4179 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004180 secondWindow->consumeMotionDown();
4181 thirdWindow->assertNoEvents();
4182
4183 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4184 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004185 mDispatcher->notifyMotion(
4186 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4187 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004188 window->assertNoEvents();
4189 secondWindow->consumeMotionMove();
4190 thirdWindow->consumeMotionDown();
4191}
4192
Prabir Pradhan814fe082022-07-22 20:22:18 +00004193TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004195 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4196 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004197 window->setFocusable(true);
4198
Patrick Williamsd828f302023-04-28 17:52:08 -05004199 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004200 setFocusedWindow(window);
4201
4202 window->consumeFocusEvent(true);
4203
Prabir Pradhan678438e2023-04-13 19:32:51 +00004204 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4205 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4206 mDispatcher->notifyKey(keyDown);
4207 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004208
4209 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4210 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4211
4212 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004213 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004214
4215 window->consumeFocusEvent(false);
4216
Prabir Pradhan678438e2023-04-13 19:32:51 +00004217 mDispatcher->notifyKey(keyDown);
4218 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004219 window->assertNoEvents();
4220}
4221
Arthur Hung96483742022-11-15 03:30:48 +00004222TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4224 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4225 "Fake Window", ADISPLAY_ID_DEFAULT);
4226 // Ensure window is non-split and have some transform.
4227 window->setPreventSplitting(true);
4228 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004229 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004230
4231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004232 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004233 {50, 50}))
4234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4235 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4236
4237 const MotionEvent secondFingerDownEvent =
4238 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4239 .displayId(ADISPLAY_ID_DEFAULT)
4240 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004241 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4242 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004243 .build();
4244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004245 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004246 InputEventInjectionSync::WAIT_FOR_RESULT))
4247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4248
4249 const MotionEvent* event = window->consumeMotion();
4250 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4251 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4252 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4253 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4254 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4255}
4256
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004257/**
4258 * Two windows: a splittable and a non-splittable.
4259 * The non-splittable window shouldn't receive any "incomplete" gestures.
4260 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4261 * The second pointer should be dropped because the initial window is splittable, so it won't get
4262 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4263 * "incomplete" gestures.
4264 */
4265TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4267 sp<FakeWindowHandle> leftWindow =
4268 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4269 ADISPLAY_ID_DEFAULT);
4270 leftWindow->setPreventSplitting(false);
4271 leftWindow->setFrame(Rect(0, 0, 100, 100));
4272 sp<FakeWindowHandle> rightWindow =
4273 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4274 ADISPLAY_ID_DEFAULT);
4275 rightWindow->setPreventSplitting(true);
4276 rightWindow->setFrame(Rect(100, 100, 200, 200));
4277 mDispatcher->onWindowInfosChanged(
4278 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4279
4280 // Touch down on left, splittable window
4281 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4282 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4283 .build());
4284 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4285
4286 mDispatcher->notifyMotion(
4287 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4288 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4289 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4290 .build());
4291 leftWindow->assertNoEvents();
4292 rightWindow->assertNoEvents();
4293}
4294
Harry Cuttsb166c002023-05-09 13:06:05 +00004295TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4296 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4297 sp<FakeWindowHandle> window =
4298 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4299 window->setFrame(Rect(0, 0, 400, 400));
4300 sp<FakeWindowHandle> trustedOverlay =
4301 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4302 ADISPLAY_ID_DEFAULT);
4303 trustedOverlay->setSpy(true);
4304 trustedOverlay->setTrustedOverlay(true);
4305
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004306 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004307
4308 // Start a three-finger touchpad swipe
4309 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4310 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4311 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4312 .build());
4313 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4314 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4315 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4316 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4317 .build());
4318 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4319 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4320 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4321 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4322 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4323 .build());
4324
4325 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4326 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4327 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4328
4329 // Move the swipe a bit
4330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4331 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4332 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4333 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4334 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4335 .build());
4336
4337 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4338
4339 // End the swipe
4340 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4341 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4342 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4343 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4344 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4345 .build());
4346 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4347 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4348 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4349 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4350 .build());
4351 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4352 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4353 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4354 .build());
4355
4356 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4357 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4358 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4359
4360 window->assertNoEvents();
4361}
4362
4363TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4365 sp<FakeWindowHandle> window =
4366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4367 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004369
4370 // Start a three-finger touchpad swipe
4371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4372 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4373 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4374 .build());
4375 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4376 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4377 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4378 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4379 .build());
4380 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4381 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4382 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4383 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4384 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4385 .build());
4386
4387 // Move the swipe a bit
4388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4389 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4390 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4391 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4392 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4393 .build());
4394
4395 // End the swipe
4396 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4397 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4398 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4399 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4400 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4401 .build());
4402 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4403 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4404 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4405 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4406 .build());
4407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4408 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4409 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4410 .build());
4411
4412 window->assertNoEvents();
4413}
4414
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004415/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004416 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4417 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004418 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004419 */
4420TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4422 sp<FakeWindowHandle> window =
4423 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4424 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004425 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004426
4427 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4428 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4429 .downTime(baseTime + 10)
4430 .eventTime(baseTime + 10)
4431 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4432 .build());
4433
4434 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4435
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004436 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004437 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004438
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004440
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004441 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4442 .downTime(baseTime + 10)
4443 .eventTime(baseTime + 30)
4444 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4445 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4446 .build());
4447
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004448 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4449
4450 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004451 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4452 .downTime(baseTime + 10)
4453 .eventTime(baseTime + 40)
4454 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4455 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4456 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004457
4458 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4459
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4461 .downTime(baseTime + 10)
4462 .eventTime(baseTime + 50)
4463 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4464 .build());
4465
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004466 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4467
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4469 .downTime(baseTime + 60)
4470 .eventTime(baseTime + 60)
4471 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4472 .build());
4473
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004474 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004475}
4476
4477/**
Hu Guo771a7692023-09-17 20:51:08 +08004478 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4479 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4480 * its coordinates should be converted by the transform of the windows of target screen.
4481 */
4482TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4483 // This case will create a window and a spy window on the default display and mirror
4484 // window on the second display. cancel event is sent through spy window pilferPointers
4485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4486
4487 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4488 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4489 spyWindowDefaultDisplay->setTrustedOverlay(true);
4490 spyWindowDefaultDisplay->setSpy(true);
4491
4492 sp<FakeWindowHandle> windowDefaultDisplay =
4493 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4494 ADISPLAY_ID_DEFAULT);
4495 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4496
4497 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4498 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4499
4500 // Add the windows to the dispatcher
4501 mDispatcher->onWindowInfosChanged(
4502 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4503 *windowSecondDisplay->getInfo()},
4504 {},
4505 0,
4506 0});
4507
4508 // Send down to ADISPLAY_ID_DEFAULT
4509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4510 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4511 {100, 100}))
4512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4513
4514 spyWindowDefaultDisplay->consumeMotionDown();
4515 windowDefaultDisplay->consumeMotionDown();
4516
4517 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4518
4519 // windowDefaultDisplay gets cancel
4520 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4521 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4522
4523 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4524 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4525 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4526 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4527 EXPECT_EQ(100, event->getX(0));
4528 EXPECT_EQ(100, event->getY(0));
4529}
4530
4531/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004532 * Ensure the correct coordinate spaces are used by InputDispatcher.
4533 *
4534 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4535 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4536 * space.
4537 */
4538class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4539public:
4540 void SetUp() override {
4541 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004542 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004543 }
4544
4545 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4546 gui::DisplayInfo info;
4547 info.displayId = displayId;
4548 info.transform = transform;
4549 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004550 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004551 }
4552
4553 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4554 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004555 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004556 }
4557
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004558 void removeAllWindowsAndDisplays() {
4559 mDisplayInfos.clear();
4560 mWindowInfos.clear();
4561 }
4562
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004563 // Set up a test scenario where the display has a scaled projection and there are two windows
4564 // on the display.
4565 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4566 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4567 // respectively.
4568 ui::Transform displayTransform;
4569 displayTransform.set(2, 0, 0, 4);
4570 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4571
4572 std::shared_ptr<FakeApplicationHandle> application =
4573 std::make_shared<FakeApplicationHandle>();
4574
4575 // Add two windows to the display. Their frames are represented in the display space.
4576 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004577 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4578 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004579 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4580 addWindow(firstWindow);
4581
4582 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004583 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4584 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004585 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4586 addWindow(secondWindow);
4587 return {std::move(firstWindow), std::move(secondWindow)};
4588 }
4589
4590private:
4591 std::vector<gui::DisplayInfo> mDisplayInfos;
4592 std::vector<gui::WindowInfo> mWindowInfos;
4593};
4594
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004595TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004596 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4597 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004598 // selected so that if the hit test was performed with the point and the bounds being in
4599 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004600 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4601 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4602 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004603
4604 firstWindow->consumeMotionDown();
4605 secondWindow->assertNoEvents();
4606}
4607
4608// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4609// the event should be treated as being in the logical display space.
4610TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4611 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4612 // Send down to the first window. The point is represented in the logical display space. The
4613 // point is selected so that if the hit test was done in logical display space, then it would
4614 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004615 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004616 PointF{75 * 2, 55 * 4});
4617
4618 firstWindow->consumeMotionDown();
4619 secondWindow->assertNoEvents();
4620}
4621
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004622// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4623// event should be treated as being in the logical display space.
4624TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4625 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4626
4627 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4628 ui::Transform injectedEventTransform;
4629 injectedEventTransform.set(matrix);
4630 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4631 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4632
4633 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4634 .displayId(ADISPLAY_ID_DEFAULT)
4635 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004636 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004637 .x(untransformedPoint.x)
4638 .y(untransformedPoint.y))
4639 .build();
4640 event.transform(matrix);
4641
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004642 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004643 InputEventInjectionSync::WAIT_FOR_RESULT);
4644
4645 firstWindow->consumeMotionDown();
4646 secondWindow->assertNoEvents();
4647}
4648
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004649TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4650 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4651
4652 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004653 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4654 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4655 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004656
4657 firstWindow->assertNoEvents();
4658 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004659 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004660 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4661
4662 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4663 EXPECT_EQ(300, event->getRawX(0));
4664 EXPECT_EQ(880, event->getRawY(0));
4665
4666 // Ensure that the x and y values are in the window's coordinate space.
4667 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4668 // the logical display space. This will be the origin of the window space.
4669 EXPECT_EQ(100, event->getX(0));
4670 EXPECT_EQ(80, event->getY(0));
4671}
4672
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004673TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4674 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4675 // The monitor will always receive events in the logical display's coordinate space, because
4676 // it does not have a window.
4677 FakeMonitorReceiver monitor{mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
4678
4679 // Send down to the first window.
4680 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4681 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4682 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4683 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4684
4685 // Second pointer goes down on second window.
4686 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4687 ADISPLAY_ID_DEFAULT,
4688 {PointF{50, 100}, PointF{150, 220}}));
4689 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4690 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4691 {1, PointF{300, 880}}};
4692 monitor.consumeMotionEvent(
4693 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4694
4695 mDispatcher->cancelCurrentTouch();
4696
4697 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4698 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4699 monitor.consumeMotionEvent(
4700 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4701}
4702
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004703TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4704 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4705
4706 // Send down to the first window.
4707 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4708 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4709 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4710
4711 // The pointer is transferred to the second window, and the second window receives it in the
4712 // correct coordinate space.
4713 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4714 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4715 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4716}
4717
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004718/** Ensure consistent behavior of InputDispatcher in all orientations. */
4719class InputDispatcherDisplayOrientationFixture
4720 : public InputDispatcherDisplayProjectionTest,
4721 public ::testing::WithParamInterface<ui::Rotation> {};
4722
4723// This test verifies the touchable region of a window for all rotations of the display by tapping
4724// in different locations on the display, specifically points close to the four corners of a
4725// window.
4726TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4727 constexpr static int32_t displayWidth = 400;
4728 constexpr static int32_t displayHeight = 800;
4729
4730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4731
4732 const auto rotation = GetParam();
4733
4734 // Set up the display with the specified rotation.
4735 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4736 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4737 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4738 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4739 logicalDisplayWidth, logicalDisplayHeight);
4740 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4741
4742 // Create a window with its bounds determined in the logical display.
4743 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4744 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4745 sp<FakeWindowHandle> window =
4746 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4747 window->setFrame(frameInDisplay, displayTransform);
4748 addWindow(window);
4749
4750 // The following points in logical display space should be inside the window.
4751 static const std::array<vec2, 4> insidePoints{
4752 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4753 for (const auto pointInsideWindow : insidePoints) {
4754 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4755 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004756 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4757 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4758 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004759 window->consumeMotionDown();
4760
Prabir Pradhan678438e2023-04-13 19:32:51 +00004761 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4762 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4763 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004764 window->consumeMotionUp();
4765 }
4766
4767 // The following points in logical display space should be outside the window.
4768 static const std::array<vec2, 5> outsidePoints{
4769 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4770 for (const auto pointOutsideWindow : outsidePoints) {
4771 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4772 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004773 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4774 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4775 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004776
Prabir Pradhan678438e2023-04-13 19:32:51 +00004777 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4778 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4779 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004780 }
4781 window->assertNoEvents();
4782}
4783
4784// Run the precision tests for all rotations.
4785INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4786 InputDispatcherDisplayOrientationFixture,
4787 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4788 ui::ROTATION_270),
4789 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4790 return ftl::enum_string(testParamInfo.param);
4791 });
4792
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004793using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4794 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004795
4796class TransferTouchFixture : public InputDispatcherTest,
4797 public ::testing::WithParamInterface<TransferFunction> {};
4798
4799TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004800 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004801
4802 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004803 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004804 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4805 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004806 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004807 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004808 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4809 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004810 sp<FakeWindowHandle> wallpaper =
4811 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4812 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004813 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004814 mDispatcher->onWindowInfosChanged(
4815 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004816
4817 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004818 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4819 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004820
Svet Ganov5d3bc372020-01-26 23:11:07 -08004821 // Only the first window should get the down event
4822 firstWindow->consumeMotionDown();
4823 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004824 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004825
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004826 // Transfer touch to the second window
4827 TransferFunction f = GetParam();
4828 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4829 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004830 // The first window gets cancel and the second gets down
4831 firstWindow->consumeMotionCancel();
4832 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004833 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004834
4835 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004836 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4837 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004838 // The first window gets no events and the second gets up
4839 firstWindow->assertNoEvents();
4840 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004841 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004842}
4843
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004844/**
4845 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4846 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4847 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4848 * natural to the user.
4849 * In this test, we are sending a pointer to both spy window and first window. We then try to
4850 * transfer touch to the second window. The dispatcher should identify the first window as the
4851 * one that should lose the gesture, and therefore the action should be to move the gesture from
4852 * the first window to the second.
4853 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4854 * the other API, as well.
4855 */
4856TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4858
4859 // Create a couple of windows + a spy window
4860 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004861 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004862 spyWindow->setTrustedOverlay(true);
4863 spyWindow->setSpy(true);
4864 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004865 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004866 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004867 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004868
4869 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004870 mDispatcher->onWindowInfosChanged(
4871 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004872
4873 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004874 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4875 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004876 // Only the first window and spy should get the down event
4877 spyWindow->consumeMotionDown();
4878 firstWindow->consumeMotionDown();
4879
4880 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4881 // if f === 'transferTouch'.
4882 TransferFunction f = GetParam();
4883 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4884 ASSERT_TRUE(success);
4885 // The first window gets cancel and the second gets down
4886 firstWindow->consumeMotionCancel();
4887 secondWindow->consumeMotionDown();
4888
4889 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004890 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4891 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004892 // The first window gets no events and the second+spy get up
4893 firstWindow->assertNoEvents();
4894 spyWindow->consumeMotionUp();
4895 secondWindow->consumeMotionUp();
4896}
4897
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004898TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004900
4901 PointF touchPoint = {10, 10};
4902
4903 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004904 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004905 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4906 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004907 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004908 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004909 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4910 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004911 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004912
4913 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004914 mDispatcher->onWindowInfosChanged(
4915 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004916
4917 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004918 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4919 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4920 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004921 // Only the first window should get the down event
4922 firstWindow->consumeMotionDown();
4923 secondWindow->assertNoEvents();
4924
4925 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004926 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4927 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004928 // Only the first window should get the pointer down event
4929 firstWindow->consumeMotionPointerDown(1);
4930 secondWindow->assertNoEvents();
4931
4932 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004933 TransferFunction f = GetParam();
4934 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4935 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004936 // The first window gets cancel and the second gets down and pointer down
4937 firstWindow->consumeMotionCancel();
4938 secondWindow->consumeMotionDown();
4939 secondWindow->consumeMotionPointerDown(1);
4940
4941 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004942 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4943 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004944 // The first window gets nothing and the second gets pointer up
4945 firstWindow->assertNoEvents();
4946 secondWindow->consumeMotionPointerUp(1);
4947
4948 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004949 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4950 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004951 // The first window gets nothing and the second gets up
4952 firstWindow->assertNoEvents();
4953 secondWindow->consumeMotionUp();
4954}
4955
Arthur Hungc539dbb2022-12-08 07:45:36 +00004956TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4958
4959 // Create a couple of windows
4960 sp<FakeWindowHandle> firstWindow =
4961 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4962 ADISPLAY_ID_DEFAULT);
4963 firstWindow->setDupTouchToWallpaper(true);
4964 sp<FakeWindowHandle> secondWindow =
4965 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4966 ADISPLAY_ID_DEFAULT);
4967 secondWindow->setDupTouchToWallpaper(true);
4968
4969 sp<FakeWindowHandle> wallpaper1 =
4970 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4971 wallpaper1->setIsWallpaper(true);
4972
4973 sp<FakeWindowHandle> wallpaper2 =
4974 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4975 wallpaper2->setIsWallpaper(true);
4976 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004977 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4978 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4979 {},
4980 0,
4981 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004982
4983 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004984 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4985 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004986
4987 // Only the first window should get the down event
4988 firstWindow->consumeMotionDown();
4989 secondWindow->assertNoEvents();
4990 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4991 wallpaper2->assertNoEvents();
4992
4993 // Transfer touch focus to the second window
4994 TransferFunction f = GetParam();
4995 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4996 ASSERT_TRUE(success);
4997
4998 // The first window gets cancel and the second gets down
4999 firstWindow->consumeMotionCancel();
5000 secondWindow->consumeMotionDown();
5001 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5002 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5003
5004 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005005 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5006 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005007 // The first window gets no events and the second gets up
5008 firstWindow->assertNoEvents();
5009 secondWindow->consumeMotionUp();
5010 wallpaper1->assertNoEvents();
5011 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5012}
5013
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005014// For the cases of single pointer touch and two pointers non-split touch, the api's
5015// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5016// for the case where there are multiple pointers split across several windows.
5017INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5018 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005019 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5020 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005021 return dispatcher->transferTouch(destChannelToken,
5022 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005023 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005024 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5025 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005026 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005027 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005028 }));
5029
Svet Ganov5d3bc372020-01-26 23:11:07 -08005030TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005032
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005033 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005034 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5035 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005036 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005037
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005038 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005039 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5040 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005041 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005042
5043 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005044 mDispatcher->onWindowInfosChanged(
5045 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005046
5047 PointF pointInFirst = {300, 200};
5048 PointF pointInSecond = {300, 600};
5049
5050 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005051 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5052 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5053 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005054 // Only the first window should get the down event
5055 firstWindow->consumeMotionDown();
5056 secondWindow->assertNoEvents();
5057
5058 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005059 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5060 ADISPLAY_ID_DEFAULT,
5061 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005062 // The first window gets a move and the second a down
5063 firstWindow->consumeMotionMove();
5064 secondWindow->consumeMotionDown();
5065
5066 // Transfer touch focus to the second window
5067 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5068 // The first window gets cancel and the new gets pointer down (it already saw down)
5069 firstWindow->consumeMotionCancel();
5070 secondWindow->consumeMotionPointerDown(1);
5071
5072 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005073 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5074 ADISPLAY_ID_DEFAULT,
5075 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005076 // The first window gets nothing and the second gets pointer up
5077 firstWindow->assertNoEvents();
5078 secondWindow->consumeMotionPointerUp(1);
5079
5080 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005081 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5082 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005083 // The first window gets nothing and the second gets up
5084 firstWindow->assertNoEvents();
5085 secondWindow->consumeMotionUp();
5086}
5087
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005088// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5089// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5090// touch is not supported, so the touch should continue on those windows and the transferred-to
5091// window should get nothing.
5092TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5093 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5094
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005095 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005096 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5097 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005098 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005099
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005100 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005101 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5102 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005103 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005104
5105 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005106 mDispatcher->onWindowInfosChanged(
5107 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005108
5109 PointF pointInFirst = {300, 200};
5110 PointF pointInSecond = {300, 600};
5111
5112 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005113 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5114 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5115 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005116 // Only the first window should get the down event
5117 firstWindow->consumeMotionDown();
5118 secondWindow->assertNoEvents();
5119
5120 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005121 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5122 ADISPLAY_ID_DEFAULT,
5123 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005124 // The first window gets a move and the second a down
5125 firstWindow->consumeMotionMove();
5126 secondWindow->consumeMotionDown();
5127
5128 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005129 const bool transferred =
5130 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005131 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5132 ASSERT_FALSE(transferred);
5133 firstWindow->assertNoEvents();
5134 secondWindow->assertNoEvents();
5135
5136 // The rest of the dispatch should proceed as normal
5137 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005138 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5139 ADISPLAY_ID_DEFAULT,
5140 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005141 // The first window gets MOVE and the second gets pointer up
5142 firstWindow->consumeMotionMove();
5143 secondWindow->consumeMotionUp();
5144
5145 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005146 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5147 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005148 // The first window gets nothing and the second gets up
5149 firstWindow->consumeMotionUp();
5150 secondWindow->assertNoEvents();
5151}
5152
Arthur Hungabbb9d82021-09-01 14:52:30 +00005153// This case will create two windows and one mirrored window on the default display and mirror
5154// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5155// the windows info of second display before default display.
5156TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5158 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005159 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005160 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005161 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005162 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005163 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005164
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005165 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005166 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005167
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005168 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005169 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005170
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005171 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005172 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005173
5174 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005175 mDispatcher->onWindowInfosChanged(
5176 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5177 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5178 *secondWindowInPrimary->getInfo()},
5179 {},
5180 0,
5181 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005182
5183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005184 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005185 {50, 50}))
5186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5187
5188 // Window should receive motion event.
5189 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5190
5191 // Transfer touch focus
5192 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5193 secondWindowInPrimary->getToken()));
5194 // The first window gets cancel.
5195 firstWindowInPrimary->consumeMotionCancel();
5196 secondWindowInPrimary->consumeMotionDown();
5197
5198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005199 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005200 ADISPLAY_ID_DEFAULT, {150, 50}))
5201 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5202 firstWindowInPrimary->assertNoEvents();
5203 secondWindowInPrimary->consumeMotionMove();
5204
5205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005206 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005207 {150, 50}))
5208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5209 firstWindowInPrimary->assertNoEvents();
5210 secondWindowInPrimary->consumeMotionUp();
5211}
5212
5213// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5214// 'transferTouch' api.
5215TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5216 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5217 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005218 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005219 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005220 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005221 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005222 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005223
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005224 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005225 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005226
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005227 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005228 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005229
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005230 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005231 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005232
5233 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005234 mDispatcher->onWindowInfosChanged(
5235 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5236 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5237 *secondWindowInPrimary->getInfo()},
5238 {},
5239 0,
5240 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005241
5242 // Touch on second display.
5243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005244 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5245 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5247
5248 // Window should receive motion event.
5249 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5250
5251 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005252 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005253
5254 // The first window gets cancel.
5255 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5256 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5257
5258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005259 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005260 SECOND_DISPLAY_ID, {150, 50}))
5261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5262 firstWindowInPrimary->assertNoEvents();
5263 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5264
5265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005266 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5268 firstWindowInPrimary->assertNoEvents();
5269 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5270}
5271
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005272TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005273 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005274 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5275 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005276
Vishnu Nair47074b82020-08-14 11:54:47 -07005277 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005278 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005279 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005280
5281 window->consumeFocusEvent(true);
5282
Prabir Pradhan678438e2023-04-13 19:32:51 +00005283 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005284
5285 // Window should receive key down event.
5286 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005287
5288 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005289 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005290 mFakePolicy->assertUserActivityPoked();
5291}
5292
5293TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5295 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5296 "Fake Window", ADISPLAY_ID_DEFAULT);
5297
5298 window->setDisableUserActivity(true);
5299 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005300 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005301 setFocusedWindow(window);
5302
5303 window->consumeFocusEvent(true);
5304
5305 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5306
5307 // Window should receive key down event.
5308 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5309
5310 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005311 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005312 mFakePolicy->assertUserActivityNotPoked();
5313}
5314
5315TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5317 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5318 "Fake Window", ADISPLAY_ID_DEFAULT);
5319
5320 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005321 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005322 setFocusedWindow(window);
5323
5324 window->consumeFocusEvent(true);
5325
5326 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5327 mDispatcher->waitForIdle();
5328
5329 // System key is not passed down
5330 window->assertNoEvents();
5331
5332 // Should have poked user activity
5333 mFakePolicy->assertUserActivityPoked();
5334}
5335
5336TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5337 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5338 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5339 "Fake Window", ADISPLAY_ID_DEFAULT);
5340
5341 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005342 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005343 setFocusedWindow(window);
5344
5345 window->consumeFocusEvent(true);
5346
5347 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5348 mDispatcher->waitForIdle();
5349
5350 // System key is not passed down
5351 window->assertNoEvents();
5352
5353 // Should have poked user activity
5354 mFakePolicy->assertUserActivityPoked();
5355}
5356
5357TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5359 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5360 "Fake Window", ADISPLAY_ID_DEFAULT);
5361
5362 window->setDisableUserActivity(true);
5363 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005364 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005365 setFocusedWindow(window);
5366
5367 window->consumeFocusEvent(true);
5368
5369 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5370 mDispatcher->waitForIdle();
5371
5372 // System key is not passed down
5373 window->assertNoEvents();
5374
5375 // Should have poked user activity
5376 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005377}
5378
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005379TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5381 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5382 "Fake Window", ADISPLAY_ID_DEFAULT);
5383
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005384 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005385
5386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005387 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005388 ADISPLAY_ID_DEFAULT, {100, 100}))
5389 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5390
5391 window->consumeMotionEvent(
5392 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5393
5394 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005395 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005396 mFakePolicy->assertUserActivityPoked();
5397}
5398
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005399TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005401 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5402 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005403
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005404 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005405
Prabir Pradhan678438e2023-04-13 19:32:51 +00005406 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005407 mDispatcher->waitForIdle();
5408
5409 window->assertNoEvents();
5410}
5411
5412// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5413TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005415 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5416 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005417
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005419
5420 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005421 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005422 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005423 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5424 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005425
5426 // Window should receive only the motion event
5427 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5428 window->assertNoEvents(); // Key event or focus event will not be received
5429}
5430
arthurhungea3f4fc2020-12-21 23:18:53 +08005431TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5433
arthurhungea3f4fc2020-12-21 23:18:53 +08005434 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005435 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5436 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005437 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005438
arthurhungea3f4fc2020-12-21 23:18:53 +08005439 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005440 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5441 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005442 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005443
5444 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005445 mDispatcher->onWindowInfosChanged(
5446 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005447
5448 PointF pointInFirst = {300, 200};
5449 PointF pointInSecond = {300, 600};
5450
5451 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005452 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5453 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5454 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005455 // Only the first window should get the down event
5456 firstWindow->consumeMotionDown();
5457 secondWindow->assertNoEvents();
5458
5459 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005460 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5461 ADISPLAY_ID_DEFAULT,
5462 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005463 // The first window gets a move and the second a down
5464 firstWindow->consumeMotionMove();
5465 secondWindow->consumeMotionDown();
5466
5467 // Send pointer cancel to the second window
5468 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005469 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005470 {pointInFirst, pointInSecond});
5471 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005472 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005473 // The first window gets move and the second gets cancel.
5474 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5475 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5476
5477 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005478 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5479 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005480 // The first window gets up and the second gets nothing.
5481 firstWindow->consumeMotionUp();
5482 secondWindow->assertNoEvents();
5483}
5484
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005485TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5487
5488 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005489 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005490 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005491 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5492 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5493 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5494
Harry Cutts33476232023-01-30 19:57:29 +00005495 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005496 window->assertNoEvents();
5497 mDispatcher->waitForIdle();
5498}
5499
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005500using InputDispatcherMonitorTest = InputDispatcherTest;
5501
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005502/**
5503 * Two entities that receive touch: A window, and a global monitor.
5504 * The touch goes to the window, and then the window disappears.
5505 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5506 * for the monitor, as well.
5507 * 1. foregroundWindow
5508 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5509 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005510TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5512 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005513 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005514
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005515 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005516
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005517 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005519 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005520 {100, 200}))
5521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5522
5523 // Both the foreground window and the global monitor should receive the touch down
5524 window->consumeMotionDown();
5525 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5526
5527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005528 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005529 ADISPLAY_ID_DEFAULT, {110, 200}))
5530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5531
5532 window->consumeMotionMove();
5533 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5534
5535 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005536 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005537 window->consumeMotionCancel();
5538 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5539
5540 // If more events come in, there will be no more foreground window to send them to. This will
5541 // cause a cancel for the monitor, as well.
5542 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005543 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005544 ADISPLAY_ID_DEFAULT, {120, 200}))
5545 << "Injection should fail because the window was removed";
5546 window->assertNoEvents();
5547 // Global monitor now gets the cancel
5548 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5549}
5550
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005551TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005553 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5554 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005555 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005556
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005557 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005558
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005560 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005562 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005563 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005564}
5565
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005566TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5567 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005568
Chris Yea209fde2020-07-22 13:54:51 -07005569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005570 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5571 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005573
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005575 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005577 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005578 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005579
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005580 // Pilfer pointers from the monitor.
5581 // This should not do anything and the window should continue to receive events.
5582 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005583
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005585 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005586 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005588
5589 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5590 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005591}
5592
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005593TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005595 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5596 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005597 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005598 window->setWindowOffset(20, 40);
5599 window->setWindowTransform(0, 1, -1, 0);
5600
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005601 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005602
5603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005604 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5606 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5607 MotionEvent* event = monitor.consumeMotion();
5608 // Even though window has transform, gesture monitor must not.
5609 ASSERT_EQ(ui::Transform(), event->getTransform());
5610}
5611
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005612TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005613 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005614 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005615
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005616 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005617 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005618 << "Injection should fail if there is a monitor, but no touchable window";
5619 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005620}
5621
chaviw81e2bb92019-12-18 15:03:51 -08005622TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005624 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5625 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005626
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005627 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005628
5629 NotifyMotionArgs motionArgs =
5630 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5631 ADISPLAY_ID_DEFAULT);
5632
Prabir Pradhan678438e2023-04-13 19:32:51 +00005633 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005634 // Window should receive motion down event.
5635 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5636
5637 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005638 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005639 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5640 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5641 motionArgs.pointerCoords[0].getX() - 10);
5642
Prabir Pradhan678438e2023-04-13 19:32:51 +00005643 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005644 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005645 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005646}
5647
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005648/**
5649 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5650 * the device default right away. In the test scenario, we check both the default value,
5651 * and the action of enabling / disabling.
5652 */
5653TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005655 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5656 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005657 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005658
5659 // Set focused application.
5660 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005661 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005662
5663 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005664 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005665 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005666 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005667
5668 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005669 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005670 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005671 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005672
5673 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005674 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005675 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005676 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005677 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005678 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005679 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005680 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005681
5682 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005683 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005685 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005686
5687 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005688 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005689 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005690 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005691 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005693 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005694 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005695
5696 window->assertNoEvents();
5697}
5698
Gang Wange9087892020-01-07 12:17:14 -05005699TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005701 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5702 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005703
5704 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005705 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005706
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005707 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005708 setFocusedWindow(window);
5709
Harry Cutts33476232023-01-30 19:57:29 +00005710 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005711
Prabir Pradhan678438e2023-04-13 19:32:51 +00005712 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5713 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005714
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005715 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005716 ASSERT_NE(event, nullptr);
5717
5718 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5719 ASSERT_NE(verified, nullptr);
5720 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5721
5722 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5723 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5724 ASSERT_EQ(keyArgs.source, verified->source);
5725 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5726
5727 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5728
5729 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005730 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005731 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005732 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5733 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5734 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5735 ASSERT_EQ(0, verifiedKey.repeatCount);
5736}
5737
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005738TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005740 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5741 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005742
5743 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5744
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005745 ui::Transform transform;
5746 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5747
5748 gui::DisplayInfo displayInfo;
5749 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5750 displayInfo.transform = transform;
5751
Patrick Williamsd828f302023-04-28 17:52:08 -05005752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005753
Prabir Pradhan678438e2023-04-13 19:32:51 +00005754 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005755 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5756 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005757 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005758
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005759 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005760 ASSERT_NE(event, nullptr);
5761
5762 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5763 ASSERT_NE(verified, nullptr);
5764 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5765
5766 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5767 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5768 EXPECT_EQ(motionArgs.source, verified->source);
5769 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5770
5771 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5772
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005773 const vec2 rawXY =
5774 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5775 motionArgs.pointerCoords[0].getXYValue());
5776 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5777 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005778 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005779 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005780 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005781 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5782 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5783}
5784
chaviw09c8d2d2020-08-24 15:48:26 -07005785/**
5786 * Ensure that separate calls to sign the same data are generating the same key.
5787 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5788 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5789 * tests.
5790 */
5791TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5792 KeyEvent event = getTestKeyEvent();
5793 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5794
5795 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5796 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5797 ASSERT_EQ(hmac1, hmac2);
5798}
5799
5800/**
5801 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5802 */
5803TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5804 KeyEvent event = getTestKeyEvent();
5805 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5806 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5807
5808 verifiedEvent.deviceId += 1;
5809 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5810
5811 verifiedEvent.source += 1;
5812 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5813
5814 verifiedEvent.eventTimeNanos += 1;
5815 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5816
5817 verifiedEvent.displayId += 1;
5818 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5819
5820 verifiedEvent.action += 1;
5821 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5822
5823 verifiedEvent.downTimeNanos += 1;
5824 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5825
5826 verifiedEvent.flags += 1;
5827 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5828
5829 verifiedEvent.keyCode += 1;
5830 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5831
5832 verifiedEvent.scanCode += 1;
5833 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5834
5835 verifiedEvent.metaState += 1;
5836 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5837
5838 verifiedEvent.repeatCount += 1;
5839 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5840}
5841
Vishnu Nair958da932020-08-21 17:12:37 -07005842TEST_F(InputDispatcherTest, SetFocusedWindow) {
5843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5844 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005845 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005846 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005847 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005848 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5849
5850 // Top window is also focusable but is not granted focus.
5851 windowTop->setFocusable(true);
5852 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005853 mDispatcher->onWindowInfosChanged(
5854 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005855 setFocusedWindow(windowSecond);
5856
5857 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005859 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005860
5861 // Focused window should receive event.
5862 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5863 windowTop->assertNoEvents();
5864}
5865
5866TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5868 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005869 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005870 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5871
5872 window->setFocusable(true);
5873 // Release channel for window is no longer valid.
5874 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005875 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005876 setFocusedWindow(window);
5877
5878 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005879 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005880
5881 // window channel is invalid, so it should not receive any input event.
5882 window->assertNoEvents();
5883}
5884
5885TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5886 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5887 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005888 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005889 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005890 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5891
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005892 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005893 setFocusedWindow(window);
5894
5895 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005896 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005897
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005898 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005899 window->assertNoEvents();
5900}
5901
5902TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5904 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005905 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005906 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005907 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005908 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5909
5910 windowTop->setFocusable(true);
5911 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005912 mDispatcher->onWindowInfosChanged(
5913 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005914 setFocusedWindow(windowTop);
5915 windowTop->consumeFocusEvent(true);
5916
Chavi Weingarten847e8512023-03-29 00:26:09 +00005917 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005918 mDispatcher->onWindowInfosChanged(
5919 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005920 windowSecond->consumeFocusEvent(true);
5921 windowTop->consumeFocusEvent(false);
5922
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005924 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005925
5926 // Focused window should receive event.
5927 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5928}
5929
Chavi Weingarten847e8512023-03-29 00:26:09 +00005930TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5932 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005933 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005934 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005935 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005936 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5937
5938 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005939 windowSecond->setFocusable(false);
5940 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005941 mDispatcher->onWindowInfosChanged(
5942 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005943 setFocusedWindow(windowTop);
5944 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005945
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005947 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005948
5949 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005950 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005951 windowSecond->assertNoEvents();
5952}
5953
5954TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5956 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005957 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005958 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005959 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5960 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005961 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5962
5963 window->setFocusable(true);
5964 previousFocusedWindow->setFocusable(true);
5965 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005966 mDispatcher->onWindowInfosChanged(
5967 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005968 setFocusedWindow(previousFocusedWindow);
5969 previousFocusedWindow->consumeFocusEvent(true);
5970
5971 // Requesting focus on invisible window takes focus from currently focused window.
5972 setFocusedWindow(window);
5973 previousFocusedWindow->consumeFocusEvent(false);
5974
5975 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005977 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5978 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005979
5980 // Window does not get focus event or key down.
5981 window->assertNoEvents();
5982
5983 // Window becomes visible.
5984 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005985 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005986
5987 // Window receives focus event.
5988 window->consumeFocusEvent(true);
5989 // Focused window receives key down.
5990 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5991}
5992
Vishnu Nair599f1412021-06-21 10:39:58 -07005993TEST_F(InputDispatcherTest, DisplayRemoved) {
5994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5995 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005996 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005997 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5998
5999 // window is granted focus.
6000 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006001 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006002 setFocusedWindow(window);
6003 window->consumeFocusEvent(true);
6004
6005 // When a display is removed window loses focus.
6006 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6007 window->consumeFocusEvent(false);
6008}
6009
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006010/**
6011 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6012 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6013 * of the 'slipperyEnterWindow'.
6014 *
6015 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6016 * a way so that the touched location is no longer covered by the top window.
6017 *
6018 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6019 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6020 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6021 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6022 * with ACTION_DOWN).
6023 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6024 * window moved itself away from the touched location and had Flag::SLIPPERY.
6025 *
6026 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6027 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6028 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6029 *
6030 * In this test, we ensure that the event received by the bottom window has
6031 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6032 */
6033TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006034 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006035 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006036
6037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6038 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6039
6040 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006041 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006042 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006043 // Make sure this one overlaps the bottom window
6044 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6045 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6046 // one. Windows with the same owner are not considered to be occluding each other.
6047 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6048
6049 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006050 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006051 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6052
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006053 mDispatcher->onWindowInfosChanged(
6054 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006055
6056 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006057 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6058 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6059 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006060 slipperyExitWindow->consumeMotionDown();
6061 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006062 mDispatcher->onWindowInfosChanged(
6063 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006064
Prabir Pradhan678438e2023-04-13 19:32:51 +00006065 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6066 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6067 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006068
6069 slipperyExitWindow->consumeMotionCancel();
6070
6071 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6072 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6073}
6074
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006075/**
6076 * Two windows, one on the left and another on the right. The left window is slippery. The right
6077 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6078 * touch moves from the left window into the right window, the gesture should continue to go to the
6079 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6080 * reproduces a crash.
6081 */
6082TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6084
6085 sp<FakeWindowHandle> leftSlipperyWindow =
6086 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6087 leftSlipperyWindow->setSlippery(true);
6088 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6089
6090 sp<FakeWindowHandle> rightDropTouchesWindow =
6091 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6092 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6093 rightDropTouchesWindow->setDropInput(true);
6094
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006095 mDispatcher->onWindowInfosChanged(
6096 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006097
6098 // Start touch in the left window
6099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6100 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6101 .build());
6102 leftSlipperyWindow->consumeMotionDown();
6103
6104 // And move it into the right window
6105 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6106 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6107 .build());
6108
6109 // Since the right window isn't eligible to receive input, touch does not slip.
6110 // The left window continues to receive the gesture.
6111 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6112 rightDropTouchesWindow->assertNoEvents();
6113}
6114
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006115/**
6116 * A single window is on screen first. Touch is injected into that window. Next, a second window
6117 * appears. Since the first window is slippery, touch will move from the first window to the second.
6118 */
6119TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6120 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6121 sp<FakeWindowHandle> originalWindow =
6122 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6123 originalWindow->setFrame(Rect(0, 0, 200, 200));
6124 originalWindow->setSlippery(true);
6125
6126 sp<FakeWindowHandle> appearingWindow =
6127 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6128 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6129
6130 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6131
6132 // Touch down on the original window
6133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6134 injectMotionEvent(*mDispatcher,
6135 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6136 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6137 .build()));
6138 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6139
6140 // Now, a new window appears. This could be, for example, a notification shade that appears
6141 // after user starts to drag down on the launcher window.
6142 mDispatcher->onWindowInfosChanged(
6143 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6145 injectMotionEvent(*mDispatcher,
6146 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6147 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6148 .build()));
6149 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6150 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6152 injectMotionEvent(*mDispatcher,
6153 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6154 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6155 .build()));
6156 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6157
6158 originalWindow->assertNoEvents();
6159 appearingWindow->assertNoEvents();
6160}
6161
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006162TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006163 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6165
6166 sp<FakeWindowHandle> leftWindow =
6167 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6168 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006169 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006170
6171 sp<FakeWindowHandle> rightSpy =
6172 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6173 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006174 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006175 rightSpy->setSpy(true);
6176 rightSpy->setTrustedOverlay(true);
6177
6178 sp<FakeWindowHandle> rightWindow =
6179 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6180 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006181 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006183 mDispatcher->onWindowInfosChanged(
6184 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006185
6186 // Touch in the left window
6187 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6188 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6189 .build());
6190 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6191 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006192 ASSERT_NO_FATAL_FAILURE(
6193 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006194
6195 // Touch another finger over the right windows
6196 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6197 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6198 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6199 .build());
6200 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6201 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6202 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6203 mDispatcher->waitForIdle();
6204 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006205 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6206 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006207
6208 // Release finger over left window. The UP actions are not treated as device interaction.
6209 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6210 // is part of the UP action, we do not treat this as device interaction.
6211 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6212 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6213 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6214 .build());
6215 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6216 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6217 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6218 mDispatcher->waitForIdle();
6219 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6220
6221 // Move remaining finger
6222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6223 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6224 .build());
6225 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6226 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6227 mDispatcher->waitForIdle();
6228 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006229 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006230
6231 // Release all fingers
6232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6233 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6234 .build());
6235 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6236 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6237 mDispatcher->waitForIdle();
6238 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6239}
6240
6241TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6242 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6243
6244 sp<FakeWindowHandle> window =
6245 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6246 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006247 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006248
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006249 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006250 setFocusedWindow(window);
6251 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6252
6253 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6254 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6255 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006256 ASSERT_NO_FATAL_FAILURE(
6257 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006258
6259 // The UP actions are not treated as device interaction.
6260 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6261 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6262 mDispatcher->waitForIdle();
6263 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6264}
6265
Garfield Tan1c7bc862020-01-28 13:24:04 -08006266class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6267protected:
6268 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6269 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6270
Chris Yea209fde2020-07-22 13:54:51 -07006271 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006272 sp<FakeWindowHandle> mWindow;
6273
6274 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006275 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006276 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006277 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006278 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006279 ASSERT_EQ(OK, mDispatcher->start());
6280
6281 setUpWindow();
6282 }
6283
6284 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006285 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006286 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006287
Vishnu Nair47074b82020-08-14 11:54:47 -07006288 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006289 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006290 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006291 mWindow->consumeFocusEvent(true);
6292 }
6293
Chris Ye2ad95392020-09-01 13:44:44 -07006294 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006295 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006296 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006297 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006298 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006299
6300 // Window should receive key down event.
6301 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6302 }
6303
6304 void expectKeyRepeatOnce(int32_t repeatCount) {
6305 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006306 mWindow->consumeKeyEvent(
6307 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006308 }
6309
Chris Ye2ad95392020-09-01 13:44:44 -07006310 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006311 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006312 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006313 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006314 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006315
6316 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006317 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006318 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006319 }
6320};
6321
6322TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006323 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006324 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6325 expectKeyRepeatOnce(repeatCount);
6326 }
6327}
6328
6329TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006330 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006331 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6332 expectKeyRepeatOnce(repeatCount);
6333 }
Harry Cutts33476232023-01-30 19:57:29 +00006334 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006335 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006336 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6337 expectKeyRepeatOnce(repeatCount);
6338 }
6339}
6340
6341TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006342 sendAndConsumeKeyDown(/*deviceId=*/1);
6343 expectKeyRepeatOnce(/*repeatCount=*/1);
6344 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006345 mWindow->assertNoEvents();
6346}
6347
6348TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006349 sendAndConsumeKeyDown(/*deviceId=*/1);
6350 expectKeyRepeatOnce(/*repeatCount=*/1);
6351 sendAndConsumeKeyDown(/*deviceId=*/2);
6352 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006353 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006354 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006355 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006356 expectKeyRepeatOnce(/*repeatCount=*/2);
6357 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006358 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006359 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006360 mWindow->assertNoEvents();
6361}
6362
6363TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006364 sendAndConsumeKeyDown(/*deviceId=*/1);
6365 expectKeyRepeatOnce(/*repeatCount=*/1);
6366 sendAndConsumeKeyDown(/*deviceId=*/2);
6367 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006368 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006369 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006370 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006371 mWindow->assertNoEvents();
6372}
6373
liushenxiang42232912021-05-21 20:24:09 +08006374TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6375 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006376 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006377 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006378 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6379 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6380 mWindow->assertNoEvents();
6381}
6382
Garfield Tan1c7bc862020-01-28 13:24:04 -08006383TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006384 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006385 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006386 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006387 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006388 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6389 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6390 IdGenerator::getSource(repeatEvent->getId()));
6391 }
6392}
6393
6394TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006395 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006396 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006397
6398 std::unordered_set<int32_t> idSet;
6399 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006400 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006401 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6402 int32_t id = repeatEvent->getId();
6403 EXPECT_EQ(idSet.end(), idSet.find(id));
6404 idSet.insert(id);
6405 }
6406}
6407
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006408/* Test InputDispatcher for MultiDisplay */
6409class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6410public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006411 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006412 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006413
Chris Yea209fde2020-07-22 13:54:51 -07006414 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006415 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006416 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006417
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006418 // Set focus window for primary display, but focused display would be second one.
6419 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006420 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006421 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6422
Vishnu Nair958da932020-08-21 17:12:37 -07006423 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006424 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006425
Chris Yea209fde2020-07-22 13:54:51 -07006426 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006427 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006428 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006429 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006430 // Set focus display to second one.
6431 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6432 // Set focus window for second display.
6433 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006434 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006435 mDispatcher->onWindowInfosChanged(
6436 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006437 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006438 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006439 }
6440
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006441 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006442 InputDispatcherTest::TearDown();
6443
Chris Yea209fde2020-07-22 13:54:51 -07006444 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006445 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006446 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006447 windowInSecondary.clear();
6448 }
6449
6450protected:
Chris Yea209fde2020-07-22 13:54:51 -07006451 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006452 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006453 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006454 sp<FakeWindowHandle> windowInSecondary;
6455};
6456
6457TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6458 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006460 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006462 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006463 windowInSecondary->assertNoEvents();
6464
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006465 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006469 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006470 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006471}
6472
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006473TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006474 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006476 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006477 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006478 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006479 windowInSecondary->assertNoEvents();
6480
6481 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006483 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006484 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006485 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006486
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006487 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006488 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006490 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006491 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006492 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006493
6494 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006495 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006496 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006497 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006498 windowInSecondary->assertNoEvents();
6499}
6500
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006501// Test per-display input monitors for motion event.
6502TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006503 FakeMonitorReceiver monitorInPrimary =
6504 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6505 FakeMonitorReceiver monitorInSecondary =
6506 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006507
6508 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006510 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006512 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006513 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006514 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006515 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006516
6517 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006519 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006521 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006522 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006523 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006524 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006525
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006526 // Lift up the touch from the second display
6527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006528 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006529 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6530 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6531 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6532
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006533 // Test inject a non-pointer motion event.
6534 // If specific a display, it will dispatch to the focused window of particular display,
6535 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006536 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006537 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006539 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006540 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006541 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006542 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006543}
6544
6545// Test per-display input monitors for key event.
6546TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006547 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006548 FakeMonitorReceiver monitorInPrimary =
6549 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6550 FakeMonitorReceiver monitorInSecondary =
6551 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006552
6553 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006555 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006556 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006557 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006558 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006559 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006560}
6561
Vishnu Nair958da932020-08-21 17:12:37 -07006562TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6563 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006564 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006565 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006566 mDispatcher->onWindowInfosChanged(
6567 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6568 *windowInSecondary->getInfo()},
6569 {},
6570 0,
6571 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006572 setFocusedWindow(secondWindowInPrimary);
6573 windowInPrimary->consumeFocusEvent(false);
6574 secondWindowInPrimary->consumeFocusEvent(true);
6575
6576 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6578 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006579 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006580 windowInPrimary->assertNoEvents();
6581 windowInSecondary->assertNoEvents();
6582 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6583}
6584
Arthur Hungdfd528e2021-12-08 13:23:04 +00006585TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6586 FakeMonitorReceiver monitorInPrimary =
6587 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6588 FakeMonitorReceiver monitorInSecondary =
6589 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6590
6591 // Test touch down on primary display.
6592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006593 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6595 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6596 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6597
6598 // Test touch down on second display.
6599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006600 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006601 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6602 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6603 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6604
6605 // Trigger cancel touch.
6606 mDispatcher->cancelCurrentTouch();
6607 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6608 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6609 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6610 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6611
6612 // Test inject a move motion event, no window/monitor should receive the event.
6613 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006614 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006615 ADISPLAY_ID_DEFAULT, {110, 200}))
6616 << "Inject motion event should return InputEventInjectionResult::FAILED";
6617 windowInPrimary->assertNoEvents();
6618 monitorInPrimary.assertNoEvents();
6619
6620 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006621 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006622 SECOND_DISPLAY_ID, {110, 200}))
6623 << "Inject motion event should return InputEventInjectionResult::FAILED";
6624 windowInSecondary->assertNoEvents();
6625 monitorInSecondary.assertNoEvents();
6626}
6627
Jackal Guof9696682018-10-05 12:23:23 +08006628class InputFilterTest : public InputDispatcherTest {
6629protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006630 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6631 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006632 NotifyMotionArgs motionArgs;
6633
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006634 motionArgs =
6635 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006636 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006637 motionArgs =
6638 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006639 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006640 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006641 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006642 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006643 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006644 } else {
6645 mFakePolicy->assertFilterInputEventWasNotCalled();
6646 }
6647 }
6648
6649 void testNotifyKey(bool expectToBeFiltered) {
6650 NotifyKeyArgs keyArgs;
6651
6652 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006653 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006654 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006655 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006656 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006657
6658 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006659 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006660 } else {
6661 mFakePolicy->assertFilterInputEventWasNotCalled();
6662 }
6663 }
6664};
6665
6666// Test InputFilter for MotionEvent
6667TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6668 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006669 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6670 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006671
6672 // Enable InputFilter
6673 mDispatcher->setInputFilterEnabled(true);
6674 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006675 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6676 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006677
6678 // Disable InputFilter
6679 mDispatcher->setInputFilterEnabled(false);
6680 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006681 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6682 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006683}
6684
6685// Test InputFilter for KeyEvent
6686TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6687 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006688 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006689
6690 // Enable InputFilter
6691 mDispatcher->setInputFilterEnabled(true);
6692 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006693 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006694
6695 // Disable InputFilter
6696 mDispatcher->setInputFilterEnabled(false);
6697 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006698 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006699}
6700
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006701// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6702// logical display coordinate space.
6703TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6704 ui::Transform firstDisplayTransform;
6705 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6706 ui::Transform secondDisplayTransform;
6707 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6708
6709 std::vector<gui::DisplayInfo> displayInfos(2);
6710 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6711 displayInfos[0].transform = firstDisplayTransform;
6712 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6713 displayInfos[1].transform = secondDisplayTransform;
6714
Patrick Williamsd828f302023-04-28 17:52:08 -05006715 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006716
6717 // Enable InputFilter
6718 mDispatcher->setInputFilterEnabled(true);
6719
6720 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006721 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6722 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006723}
6724
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006725class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6726protected:
6727 virtual void SetUp() override {
6728 InputDispatcherTest::SetUp();
6729
6730 /**
6731 * We don't need to enable input filter to test the injected event policy, but we enabled it
6732 * here to make the tests more realistic, since this policy only matters when inputfilter is
6733 * on.
6734 */
6735 mDispatcher->setInputFilterEnabled(true);
6736
6737 std::shared_ptr<InputApplicationHandle> application =
6738 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006739 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6740 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006741
6742 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6743 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006744 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006745 setFocusedWindow(mWindow);
6746 mWindow->consumeFocusEvent(true);
6747 }
6748
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006749 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6750 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006751 KeyEvent event;
6752
6753 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6754 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6755 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006756 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006757 const int32_t additionalPolicyFlags =
6758 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006760 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006761 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006762 policyFlags | additionalPolicyFlags));
6763
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006764 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006765 }
6766
6767 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6768 int32_t flags) {
6769 MotionEvent event;
6770 PointerProperties pointerProperties[1];
6771 PointerCoords pointerCoords[1];
6772 pointerProperties[0].clear();
6773 pointerProperties[0].id = 0;
6774 pointerCoords[0].clear();
6775 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6776 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6777
6778 ui::Transform identityTransform;
6779 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6780 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6781 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6782 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6783 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006784 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006785 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006786 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006787
6788 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006790 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006791 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006792 policyFlags | additionalPolicyFlags));
6793
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006794 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006795 }
6796
6797private:
6798 sp<FakeWindowHandle> mWindow;
6799};
6800
6801TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006802 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6803 // filter. Without it, the event will no different from a regularly injected event, and the
6804 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006805 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6806 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006807}
6808
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006809TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006810 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006811 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006812 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6813}
6814
6815TEST_F(InputFilterInjectionPolicyTest,
6816 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6817 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006818 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006819 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006820}
6821
6822TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006823 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6824 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006825}
6826
chaviwfd6d3512019-03-25 13:23:49 -07006827class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006828 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006829 InputDispatcherTest::SetUp();
6830
Chris Yea209fde2020-07-22 13:54:51 -07006831 std::shared_ptr<FakeApplicationHandle> application =
6832 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006833 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006834 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006835 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006836
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006837 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006838 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006839 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006840
6841 // Set focused application.
6842 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006843 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006844
6845 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006846 mDispatcher->onWindowInfosChanged(
6847 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006848 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006849 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006850 }
6851
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006852 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006853 InputDispatcherTest::TearDown();
6854
6855 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006856 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006857 }
6858
6859protected:
6860 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006861 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006862 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006863};
6864
6865// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6866// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6867// the onPointerDownOutsideFocus callback.
6868TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006870 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006871 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006873 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006874
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006875 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006876 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6877}
6878
6879// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6880// DOWN on the window that doesn't have focus. Ensure no window received the
6881// onPointerDownOutsideFocus callback.
6882TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006884 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6885 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006887 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006888
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006889 ASSERT_TRUE(mDispatcher->waitForIdle());
6890 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006891}
6892
6893// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6894// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6895TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006897 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006898 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006899 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006900
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006901 ASSERT_TRUE(mDispatcher->waitForIdle());
6902 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006903}
6904
6905// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6906// DOWN on the window that already has focus. Ensure no window received the
6907// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006908TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006910 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006911 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006913 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006914
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006915 ASSERT_TRUE(mDispatcher->waitForIdle());
6916 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006917}
6918
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006919// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6920// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6921TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6922 const MotionEvent event =
6923 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6924 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006925 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006926 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6927 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6930 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6931
6932 ASSERT_TRUE(mDispatcher->waitForIdle());
6933 mFakePolicy->assertOnPointerDownWasNotCalled();
6934 // Ensure that the unfocused window did not receive any FOCUS events.
6935 mUnfocusedWindow->assertNoEvents();
6936}
6937
chaviwaf87b3e2019-10-01 16:59:28 -07006938// These tests ensures we can send touch events to a single client when there are multiple input
6939// windows that point to the same client token.
6940class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6941 virtual void SetUp() override {
6942 InputDispatcherTest::SetUp();
6943
Chris Yea209fde2020-07-22 13:54:51 -07006944 std::shared_ptr<FakeApplicationHandle> application =
6945 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006946 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6947 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006948 mWindow1->setFrame(Rect(0, 0, 100, 100));
6949
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006950 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6951 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006952 mWindow2->setFrame(Rect(100, 100, 200, 200));
6953
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006954 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006955 }
6956
6957protected:
6958 sp<FakeWindowHandle> mWindow1;
6959 sp<FakeWindowHandle> mWindow2;
6960
6961 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006962 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006963 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6964 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006965 }
6966
6967 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6968 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006969 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006970 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006971
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006972 ASSERT_NE(nullptr, motionEvent)
6973 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006974
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006975 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006976 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006977
6978 for (size_t i = 0; i < points.size(); i++) {
6979 float expectedX = points[i].x;
6980 float expectedY = points[i].y;
6981
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006982 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006983 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006984 << ", got " << motionEvent->getX(i);
6985 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006986 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006987 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006988 }
6989 }
chaviw9eaa22c2020-07-01 16:21:27 -07006990
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006991 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006992 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006993 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6994 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006995
6996 // Always consume from window1 since it's the window that has the InputReceiver
6997 consumeMotionEvent(mWindow1, action, expectedPoints);
6998 }
chaviwaf87b3e2019-10-01 16:59:28 -07006999};
7000
7001TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7002 // Touch Window 1
7003 PointF touchedPoint = {10, 10};
7004 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007005 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007006
7007 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007008 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007009
7010 // Touch Window 2
7011 touchedPoint = {150, 150};
7012 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007013 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007014}
7015
chaviw9eaa22c2020-07-01 16:21:27 -07007016TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7017 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007018 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007019 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007020
7021 // Touch Window 1
7022 PointF touchedPoint = {10, 10};
7023 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007024 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007025 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007026 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007027
7028 // Touch Window 2
7029 touchedPoint = {150, 150};
7030 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007031 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7032 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007033
chaviw9eaa22c2020-07-01 16:21:27 -07007034 // Update the transform so rotation is set
7035 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007036 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007037 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7038 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007039}
7040
chaviw9eaa22c2020-07-01 16:21:27 -07007041TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007042 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007043 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007044
7045 // Touch Window 1
7046 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7047 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007048 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007049
7050 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007051 touchedPoints.push_back(PointF{150, 150});
7052 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007053 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007054
chaviw9eaa22c2020-07-01 16:21:27 -07007055 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007056 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007057 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007058
chaviw9eaa22c2020-07-01 16:21:27 -07007059 // Update the transform so rotation is set for Window 2
7060 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007061 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007062 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007063 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007064}
7065
chaviw9eaa22c2020-07-01 16:21:27 -07007066TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007067 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007068 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007069
7070 // Touch Window 1
7071 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7072 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007073 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007074
7075 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007076 touchedPoints.push_back(PointF{150, 150});
7077 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007078
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007079 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007080
7081 // Move both windows
7082 touchedPoints = {{20, 20}, {175, 175}};
7083 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7084 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7085
chaviw9eaa22c2020-07-01 16:21:27 -07007086 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007087
chaviw9eaa22c2020-07-01 16:21:27 -07007088 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007089 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007090 expectedPoints.pop_back();
7091
7092 // Touch Window 2
7093 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007094 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007095 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007096 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007097
7098 // Move both windows
7099 touchedPoints = {{20, 20}, {175, 175}};
7100 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7101 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7102
7103 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007104}
7105
7106TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7107 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007108 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007109
7110 // Touch Window 1
7111 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7112 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007113 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007114
7115 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007116 touchedPoints.push_back(PointF{150, 150});
7117 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007118
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007119 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007120
7121 // Move both windows
7122 touchedPoints = {{20, 20}, {175, 175}};
7123 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7124 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7125
chaviw9eaa22c2020-07-01 16:21:27 -07007126 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007127}
7128
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007129/**
7130 * When one of the windows is slippery, the touch should not slip into the other window with the
7131 * same input channel.
7132 */
7133TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7134 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007135 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007136
7137 // Touch down in window 1
7138 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7139 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7140 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7141
7142 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7143 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7144 // getting generated.
7145 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7146 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7147
7148 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7149}
7150
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007151/**
7152 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7153 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7154 * that the pointer is hovering over may have a different transform.
7155 */
7156TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007157 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007158
7159 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7161 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7162 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007163 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7164 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007165 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007166 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7167 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7168 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007169 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7170 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7171 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7172}
7173
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007174class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7175 virtual void SetUp() override {
7176 InputDispatcherTest::SetUp();
7177
Chris Yea209fde2020-07-22 13:54:51 -07007178 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007179 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007180 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7181 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007182 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007183 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007184 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007185
7186 // Set focused application.
7187 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7188
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007189 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007190 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007191 mWindow->consumeFocusEvent(true);
7192 }
7193
7194 virtual void TearDown() override {
7195 InputDispatcherTest::TearDown();
7196 mWindow.clear();
7197 }
7198
7199protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007200 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007201 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007202 sp<FakeWindowHandle> mWindow;
7203 static constexpr PointF WINDOW_LOCATION = {20, 20};
7204
7205 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007207 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007208 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007210 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007211 WINDOW_LOCATION));
7212 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007213
7214 sp<FakeWindowHandle> addSpyWindow() {
7215 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007216 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007217 spy->setTrustedOverlay(true);
7218 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007219 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007220 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007221 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007222 return spy;
7223 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007224};
7225
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007226// Send a tap and respond, which should not cause an ANR.
7227TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7228 tapOnWindow();
7229 mWindow->consumeMotionDown();
7230 mWindow->consumeMotionUp();
7231 ASSERT_TRUE(mDispatcher->waitForIdle());
7232 mFakePolicy->assertNotifyAnrWasNotCalled();
7233}
7234
7235// Send a regular key and respond, which should not cause an ANR.
7236TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007238 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7239 ASSERT_TRUE(mDispatcher->waitForIdle());
7240 mFakePolicy->assertNotifyAnrWasNotCalled();
7241}
7242
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007243TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7244 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007245 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007246 mWindow->consumeFocusEvent(false);
7247
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007248 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007249 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7250 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007251 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007253 // Key will not go to window because we have no focused window.
7254 // The 'no focused window' ANR timer should start instead.
7255
7256 // Now, the focused application goes away.
7257 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7258 // The key should get dropped and there should be no ANR.
7259
7260 ASSERT_TRUE(mDispatcher->waitForIdle());
7261 mFakePolicy->assertNotifyAnrWasNotCalled();
7262}
7263
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007264// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007265// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7266// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007267TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007269 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007270 WINDOW_LOCATION));
7271
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007272 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7273 ASSERT_TRUE(sequenceNum);
7274 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007275 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007276
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007277 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007278 mWindow->consumeMotionEvent(
7279 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007280 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007281 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007282}
7283
7284// Send a key to the app and have the app not respond right away.
7285TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7286 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007288 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7289 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007290 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007291 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007292 ASSERT_TRUE(mDispatcher->waitForIdle());
7293}
7294
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007295// We have a focused application, but no focused window
7296TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007297 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007298 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007299 mWindow->consumeFocusEvent(false);
7300
7301 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007303 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007304 WINDOW_LOCATION));
7305 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7306 mDispatcher->waitForIdle();
7307 mFakePolicy->assertNotifyAnrWasNotCalled();
7308
7309 // Once a focused event arrives, we get an ANR for this application
7310 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7311 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007312 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007313 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007314 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007315 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007316 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007317 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007318 ASSERT_TRUE(mDispatcher->waitForIdle());
7319}
7320
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007321/**
7322 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7323 * there will not be an ANR.
7324 */
7325TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7326 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007327 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007328 mWindow->consumeFocusEvent(false);
7329
7330 KeyEvent event;
7331 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7332 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7333
7334 // Define a valid key down event that is stale (too old).
7335 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007336 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007337 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007338
7339 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7340
7341 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007342 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007343 InputEventInjectionSync::WAIT_FOR_RESULT,
7344 INJECT_EVENT_TIMEOUT, policyFlags);
7345 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7346 << "Injection should fail because the event is stale";
7347
7348 ASSERT_TRUE(mDispatcher->waitForIdle());
7349 mFakePolicy->assertNotifyAnrWasNotCalled();
7350 mWindow->assertNoEvents();
7351}
7352
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007353// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007354// Make sure that we don't notify policy twice about the same ANR.
7355TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007356 const std::chrono::duration appTimeout = 400ms;
7357 mApplication->setDispatchingTimeout(appTimeout);
7358 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7359
Vishnu Nair47074b82020-08-14 11:54:47 -07007360 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007361 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007362 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007363
7364 // Once a focused event arrives, we get an ANR for this application
7365 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7366 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007367 const std::chrono::duration eventInjectionTimeout = 100ms;
7368 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007369 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007370 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007371 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7372 /*allowKeyRepeat=*/false);
7373 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7374 << "result=" << ftl::enum_string(result);
7375 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7376 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7377 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7378 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007379
Vishnu Naire4df8752022-09-08 09:17:55 -07007380 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007381 // ANR should not be raised again. It is up to policy to do that if it desires.
7382 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007383
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007384 // If we now get a focused window, the ANR should stop, but the policy handles that via
7385 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007386 ASSERT_TRUE(mDispatcher->waitForIdle());
7387}
7388
7389// We have a focused application, but no focused window
7390TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007391 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007392 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007393 mWindow->consumeFocusEvent(false);
7394
7395 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007396 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007397
Vishnu Naire4df8752022-09-08 09:17:55 -07007398 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7399 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007400
7401 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007402 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007403 ASSERT_TRUE(mDispatcher->waitForIdle());
7404 mWindow->assertNoEvents();
7405}
7406
7407/**
7408 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7409 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7410 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7411 * the ANR mechanism should still work.
7412 *
7413 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7414 * DOWN event, while not responding on the second one.
7415 */
7416TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7417 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007418 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007419 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7420 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7421 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007422 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007423
7424 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007425 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007426 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7427 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7428 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007429 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007430
7431 // We have now sent down and up. Let's consume first event and then ANR on the second.
7432 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7433 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007434 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007435}
7436
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007437// A spy window can receive an ANR
7438TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7439 sp<FakeWindowHandle> spy = addSpyWindow();
7440
7441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007443 WINDOW_LOCATION));
7444 mWindow->consumeMotionDown();
7445
7446 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7447 ASSERT_TRUE(sequenceNum);
7448 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007449 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007450
7451 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007452 spy->consumeMotionEvent(
7453 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007454 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007455 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007456}
7457
7458// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007459// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007460TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7461 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007462
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007464 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007465 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007467
7468 // Stuck on the ACTION_UP
7469 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007470 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007471
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007472 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007473 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007474 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7475 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007476
7477 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7478 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007479 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007480 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007481 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007482}
7483
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007484// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007485// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007486TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7487 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007488
7489 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007490 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7491 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007492
7493 mWindow->consumeMotionDown();
7494 // Stuck on the ACTION_UP
7495 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007496 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007497
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007498 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007499 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007500 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7501 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007502
7503 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7504 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007505 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007506 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007507 spy->assertNoEvents();
7508}
7509
7510TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007511 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007512
7513 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7514
7515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007516 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007517 WINDOW_LOCATION));
7518
7519 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7520 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7521 ASSERT_TRUE(consumeSeq);
7522
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007523 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7524 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007525
7526 monitor.finishEvent(*consumeSeq);
7527 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7528
7529 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007530 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007531}
7532
7533// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7534// process events, you don't get an anr. When the window later becomes unresponsive again, you
7535// get an ANR again.
7536// 1. tap -> block on ACTION_UP -> receive ANR
7537// 2. consume all pending events (= queue becomes healthy again)
7538// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7539TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7540 tapOnWindow();
7541
7542 mWindow->consumeMotionDown();
7543 // Block on ACTION_UP
7544 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007545 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007546 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7547 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007548 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007549 mWindow->assertNoEvents();
7550
7551 tapOnWindow();
7552 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007553 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007554 mWindow->consumeMotionUp();
7555
7556 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007557 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007558 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007559 mWindow->assertNoEvents();
7560}
7561
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007562// If a connection remains unresponsive for a while, make sure policy is only notified once about
7563// it.
7564TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007566 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007567 WINDOW_LOCATION));
7568
7569 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007570 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007571 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007572 // 'notifyConnectionUnresponsive' should only be called once per connection
7573 mFakePolicy->assertNotifyAnrWasNotCalled();
7574 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007575 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007576 mWindow->consumeMotionEvent(
7577 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007578 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007579 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007580 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007581 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007582}
7583
7584/**
7585 * 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 -07007586 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007587 *
7588 * Warning!!!
7589 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7590 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007591 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007592 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7593 *
7594 * If that value changes, this test should also change.
7595 */
7596TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7597 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007598 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007599
7600 tapOnWindow();
7601 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7602 ASSERT_TRUE(downSequenceNum);
7603 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7604 ASSERT_TRUE(upSequenceNum);
7605 // Don't finish the events yet, and send a key
7606 // Injection will "succeed" because we will eventually give up and send the key to the focused
7607 // window even if motions are still being processed. But because the injection timeout is short,
7608 // we will receive INJECTION_TIMED_OUT as the result.
7609
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007610 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007611 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7612 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007613 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007614 // Key will not be sent to the window, yet, because the window is still processing events
7615 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007616 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7617 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7618 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7619 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007620
7621 std::this_thread::sleep_for(500ms);
7622 // if we wait long enough though, dispatcher will give up, and still send the key
7623 // to the focused window, even though we have not yet finished the motion event
7624 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7625 mWindow->finishEvent(*downSequenceNum);
7626 mWindow->finishEvent(*upSequenceNum);
7627}
7628
7629/**
7630 * If a window is processing a motion event, and then a key event comes in, the key event should
7631 * not go to the focused window until the motion is processed.
7632 * If then a new motion comes in, then the pending key event should be going to the currently
7633 * focused window right away.
7634 */
7635TEST_F(InputDispatcherSingleWindowAnr,
7636 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7637 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007638 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007639
7640 tapOnWindow();
7641 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7642 ASSERT_TRUE(downSequenceNum);
7643 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7644 ASSERT_TRUE(upSequenceNum);
7645 // Don't finish the events yet, and send a key
7646 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007648 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7649 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007650 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007651 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7652 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7653 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7654 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007655
7656 // Now tap down again. It should cause the pending key to go to the focused window right away.
7657 tapOnWindow();
7658 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7659 // the other events yet. We can finish events in any order.
7660 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7661 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7662 mWindow->consumeMotionDown();
7663 mWindow->consumeMotionUp();
7664 mWindow->assertNoEvents();
7665}
7666
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007667/**
7668 * Send an event to the app and have the app not respond right away.
7669 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7670 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7671 * At some point, the window becomes responsive again.
7672 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7673 */
7674TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7675 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7676 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7677 .build());
7678
7679 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7680 ASSERT_TRUE(sequenceNum);
7681 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7682 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7683
7684 mWindow->finishEvent(*sequenceNum);
7685 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7686 ASSERT_TRUE(mDispatcher->waitForIdle());
7687 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7688
7689 // Now that the window is responsive, let's continue the gesture.
7690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7691 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7692 .build());
7693
7694 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7695 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7696 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7697 .build());
7698
7699 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7700 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7701 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7702 .build());
7703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7704 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7705 .build());
7706 // We already canceled this pointer, so the window shouldn't get any new events.
7707 mWindow->assertNoEvents();
7708
7709 // Start another one.
7710 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7711 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7712 .build());
7713 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7714}
7715
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007716class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7717 virtual void SetUp() override {
7718 InputDispatcherTest::SetUp();
7719
Chris Yea209fde2020-07-22 13:54:51 -07007720 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007721 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007722 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7723 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007724 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007725 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007726 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007727
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007728 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7729 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007730 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007731 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007732
7733 // Set focused application.
7734 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007735 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007736
7737 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007738 mDispatcher->onWindowInfosChanged(
7739 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007740 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007741 mFocusedWindow->consumeFocusEvent(true);
7742 }
7743
7744 virtual void TearDown() override {
7745 InputDispatcherTest::TearDown();
7746
7747 mUnfocusedWindow.clear();
7748 mFocusedWindow.clear();
7749 }
7750
7751protected:
Chris Yea209fde2020-07-22 13:54:51 -07007752 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007753 sp<FakeWindowHandle> mUnfocusedWindow;
7754 sp<FakeWindowHandle> mFocusedWindow;
7755 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7756 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7757 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7758
7759 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7760
7761 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7762
7763private:
7764 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007767 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007769 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007770 location));
7771 }
7772};
7773
7774// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7775// should be ANR'd first.
7776TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007779 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007781 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007782 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007783 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784 // We consumed all events, so no ANR
7785 ASSERT_TRUE(mDispatcher->waitForIdle());
7786 mFakePolicy->assertNotifyAnrWasNotCalled();
7787
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007790 FOCUSED_WINDOW_LOCATION));
7791 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7792 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007793
7794 const std::chrono::duration timeout =
7795 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007796 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007797 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7798 // sequence to make it consistent
7799 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007800 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007801 mFocusedWindow->consumeMotionDown();
7802 // This cancel is generated because the connection was unresponsive
7803 mFocusedWindow->consumeMotionCancel();
7804 mFocusedWindow->assertNoEvents();
7805 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007806 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007807 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7808 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007809 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007810}
7811
7812// If we have 2 windows with identical timeouts that are both unresponsive,
7813// it doesn't matter which order they should have ANR.
7814// But we should receive ANR for both.
7815TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7816 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007817 mUnfocusedWindow->setDispatchingTimeout(
7818 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007819 mDispatcher->onWindowInfosChanged(
7820 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007821
7822 tapOnFocusedWindow();
7823 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007824 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007825 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7826 mFocusedWindow->getDispatchingTimeout(
7827 DISPATCHING_TIMEOUT)),
7828 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7829
7830 ASSERT_THAT(anrConnectionTokens,
7831 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7832 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007833
7834 ASSERT_TRUE(mDispatcher->waitForIdle());
7835 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007836
7837 mFocusedWindow->consumeMotionDown();
7838 mFocusedWindow->consumeMotionUp();
7839 mUnfocusedWindow->consumeMotionOutside();
7840
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007841 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7842 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007843
7844 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007845 ASSERT_THAT(responsiveTokens,
7846 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7847 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007848 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007849}
7850
7851// If a window is already not responding, the second tap on the same window should be ignored.
7852// We should also log an error to account for the dropped event (not tested here).
7853// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7854TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7855 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007856 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007857 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007858 // Receive the events, but don't respond
7859 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7860 ASSERT_TRUE(downEventSequenceNum);
7861 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7862 ASSERT_TRUE(upEventSequenceNum);
7863 const std::chrono::duration timeout =
7864 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007865 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007866
7867 // Tap once again
7868 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007869 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007870 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007871 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007872 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007873 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007874 FOCUSED_WINDOW_LOCATION));
7875 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7876 // valid touch target
7877 mUnfocusedWindow->assertNoEvents();
7878
7879 // Consume the first tap
7880 mFocusedWindow->finishEvent(*downEventSequenceNum);
7881 mFocusedWindow->finishEvent(*upEventSequenceNum);
7882 ASSERT_TRUE(mDispatcher->waitForIdle());
7883 // The second tap did not go to the focused window
7884 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007885 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007886 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7887 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007888 mFakePolicy->assertNotifyAnrWasNotCalled();
7889}
7890
7891// If you tap outside of all windows, there will not be ANR
7892TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007893 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007894 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007895 LOCATION_OUTSIDE_ALL_WINDOWS));
7896 ASSERT_TRUE(mDispatcher->waitForIdle());
7897 mFakePolicy->assertNotifyAnrWasNotCalled();
7898}
7899
7900// Since the focused window is paused, tapping on it should not produce any events
7901TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7902 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007903 mDispatcher->onWindowInfosChanged(
7904 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007905
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007906 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007907 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007908 FOCUSED_WINDOW_LOCATION));
7909
7910 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7911 ASSERT_TRUE(mDispatcher->waitForIdle());
7912 // Should not ANR because the window is paused, and touches shouldn't go to it
7913 mFakePolicy->assertNotifyAnrWasNotCalled();
7914
7915 mFocusedWindow->assertNoEvents();
7916 mUnfocusedWindow->assertNoEvents();
7917}
7918
7919/**
7920 * 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 -07007921 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007922 * If a different window becomes focused at this time, the key should go to that window instead.
7923 *
7924 * Warning!!!
7925 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7926 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007927 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007928 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7929 *
7930 * If that value changes, this test should also change.
7931 */
7932TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7933 // Set a long ANR timeout to prevent it from triggering
7934 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007935 mDispatcher->onWindowInfosChanged(
7936 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007937
7938 tapOnUnfocusedWindow();
7939 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7940 ASSERT_TRUE(downSequenceNum);
7941 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7942 ASSERT_TRUE(upSequenceNum);
7943 // Don't finish the events yet, and send a key
7944 // Injection will succeed because we will eventually give up and send the key to the focused
7945 // window even if motions are still being processed.
7946
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007947 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007948 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7949 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007951 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007952 // and the key remains pending, waiting for the touch events to be processed.
7953 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7954 // under the hood.
7955 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7956 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007957
7958 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007959 mFocusedWindow->setFocusable(false);
7960 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007961 mDispatcher->onWindowInfosChanged(
7962 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007963 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007964
7965 // Focus events should precede the key events
7966 mUnfocusedWindow->consumeFocusEvent(true);
7967 mFocusedWindow->consumeFocusEvent(false);
7968
7969 // Finish the tap events, which should unblock dispatcher
7970 mUnfocusedWindow->finishEvent(*downSequenceNum);
7971 mUnfocusedWindow->finishEvent(*upSequenceNum);
7972
7973 // Now that all queues are cleared and no backlog in the connections, the key event
7974 // can finally go to the newly focused "mUnfocusedWindow".
7975 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7976 mFocusedWindow->assertNoEvents();
7977 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007978 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007979}
7980
7981// When the touch stream is split across 2 windows, and one of them does not respond,
7982// then ANR should be raised and the touch should be canceled for the unresponsive window.
7983// The other window should not be affected by that.
7984TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7985 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007986 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7987 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7988 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007989 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007990 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007991
7992 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007993 mDispatcher->notifyMotion(
7994 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7995 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007996
7997 const std::chrono::duration timeout =
7998 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007999 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008000
8001 mUnfocusedWindow->consumeMotionDown();
8002 mFocusedWindow->consumeMotionDown();
8003 // Focused window may or may not receive ACTION_MOVE
8004 // But it should definitely receive ACTION_CANCEL due to the ANR
8005 InputEvent* event;
8006 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8007 ASSERT_TRUE(moveOrCancelSequenceNum);
8008 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8009 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008010 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008011 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8012 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8013 mFocusedWindow->consumeMotionCancel();
8014 } else {
8015 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8016 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008017 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008018 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8019 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008020
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021 mUnfocusedWindow->assertNoEvents();
8022 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008023 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008024}
8025
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008026/**
8027 * If we have no focused window, and a key comes in, we start the ANR timer.
8028 * The focused application should add a focused window before the timer runs out to prevent ANR.
8029 *
8030 * If the user touches another application during this time, the key should be dropped.
8031 * Next, if a new focused window comes in, without toggling the focused application,
8032 * then no ANR should occur.
8033 *
8034 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8035 * but in some cases the policy may not update the focused application.
8036 */
8037TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8038 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8039 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008040 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008041 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8042 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8043 mFocusedWindow->setFocusable(false);
8044
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008045 mDispatcher->onWindowInfosChanged(
8046 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008047 mFocusedWindow->consumeFocusEvent(false);
8048
8049 // Send a key. The ANR timer should start because there is no focused window.
8050 // 'focusedApplication' will get blamed if this timer completes.
8051 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008052 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008053 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8054 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008055 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008057
8058 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8059 // then the injected touches won't cause the focused event to get dropped.
8060 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8061 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8062 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8063 // For this test, it means that the key would get delivered to the window once it becomes
8064 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008065 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008066
8067 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008068 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8069 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8070 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008071
8072 // We do not consume the motion right away, because that would require dispatcher to first
8073 // process (== drop) the key event, and by that time, ANR will be raised.
8074 // Set the focused window first.
8075 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008076 mDispatcher->onWindowInfosChanged(
8077 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008078 setFocusedWindow(mFocusedWindow);
8079 mFocusedWindow->consumeFocusEvent(true);
8080 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8081 // to another application. This could be a bug / behaviour in the policy.
8082
8083 mUnfocusedWindow->consumeMotionDown();
8084
8085 ASSERT_TRUE(mDispatcher->waitForIdle());
8086 // Should not ANR because we actually have a focused window. It was just added too slowly.
8087 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8088}
8089
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008090// These tests ensure we cannot send touch events to a window that's positioned behind a window
8091// that has feature NO_INPUT_CHANNEL.
8092// Layout:
8093// Top (closest to user)
8094// mNoInputWindow (above all windows)
8095// mBottomWindow
8096// Bottom (furthest from user)
8097class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8098 virtual void SetUp() override {
8099 InputDispatcherTest::SetUp();
8100
8101 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008102 mNoInputWindow =
8103 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8104 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008105 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008106 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008107 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8108 // It's perfectly valid for this window to not have an associated input channel
8109
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008110 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8111 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008112 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8113
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008114 mDispatcher->onWindowInfosChanged(
8115 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008116 }
8117
8118protected:
8119 std::shared_ptr<FakeApplicationHandle> mApplication;
8120 sp<FakeWindowHandle> mNoInputWindow;
8121 sp<FakeWindowHandle> mBottomWindow;
8122};
8123
8124TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8125 PointF touchedPoint = {10, 10};
8126
Prabir Pradhan678438e2023-04-13 19:32:51 +00008127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8128 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8129 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008130
8131 mNoInputWindow->assertNoEvents();
8132 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8133 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8134 // and therefore should prevent mBottomWindow from receiving touches
8135 mBottomWindow->assertNoEvents();
8136}
8137
8138/**
8139 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8140 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8141 */
8142TEST_F(InputDispatcherMultiWindowOcclusionTests,
8143 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008144 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8145 "Window with input channel and NO_INPUT_CHANNEL",
8146 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008147
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008148 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008149 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008150 mDispatcher->onWindowInfosChanged(
8151 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008152
8153 PointF touchedPoint = {10, 10};
8154
Prabir Pradhan678438e2023-04-13 19:32:51 +00008155 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8156 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8157 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008158
8159 mNoInputWindow->assertNoEvents();
8160 mBottomWindow->assertNoEvents();
8161}
8162
Vishnu Nair958da932020-08-21 17:12:37 -07008163class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8164protected:
8165 std::shared_ptr<FakeApplicationHandle> mApp;
8166 sp<FakeWindowHandle> mWindow;
8167 sp<FakeWindowHandle> mMirror;
8168
8169 virtual void SetUp() override {
8170 InputDispatcherTest::SetUp();
8171 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008172 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8173 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8174 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008175 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8176 mWindow->setFocusable(true);
8177 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008178 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008179 }
8180};
8181
8182TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8183 // Request focus on a mirrored window
8184 setFocusedWindow(mMirror);
8185
8186 // window gets focused
8187 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008189 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008190 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8191}
8192
8193// A focused & mirrored window remains focused only if the window and its mirror are both
8194// focusable.
8195TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8196 setFocusedWindow(mMirror);
8197
8198 // window gets focused
8199 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008201 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008202 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008204 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008205 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8206
8207 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008208 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008209
8210 // window loses focus since one of the windows associated with the token in not focusable
8211 mWindow->consumeFocusEvent(false);
8212
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008213 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008214 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008215 mWindow->assertNoEvents();
8216}
8217
8218// A focused & mirrored window remains focused until the window and its mirror both become
8219// invisible.
8220TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8221 setFocusedWindow(mMirror);
8222
8223 // window gets focused
8224 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008226 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008227 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008229 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008230 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8231
8232 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008233 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008234
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008236 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008237 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008239 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008240 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8241
8242 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008243 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008244
8245 // window loses focus only after all windows associated with the token become invisible.
8246 mWindow->consumeFocusEvent(false);
8247
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008248 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008249 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008250 mWindow->assertNoEvents();
8251}
8252
8253// A focused & mirrored window remains focused until both windows are removed.
8254TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8255 setFocusedWindow(mMirror);
8256
8257 // window gets focused
8258 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008260 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008261 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008263 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008264 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8265
8266 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008267 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008268
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008270 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008271 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008273 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008274 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8275
8276 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008277 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008278 mWindow->consumeFocusEvent(false);
8279
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008280 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008281 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008282 mWindow->assertNoEvents();
8283}
8284
8285// Focus request can be pending until one window becomes visible.
8286TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8287 // Request focus on an invisible mirror.
8288 mWindow->setVisible(false);
8289 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008290 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008291 setFocusedWindow(mMirror);
8292
8293 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008295 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8296 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008297
8298 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008299 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008300
8301 // window gets focused
8302 mWindow->consumeFocusEvent(true);
8303 // window gets the pending key event
8304 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8305}
Prabir Pradhan99987712020-11-10 18:43:05 -08008306
8307class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8308protected:
8309 std::shared_ptr<FakeApplicationHandle> mApp;
8310 sp<FakeWindowHandle> mWindow;
8311 sp<FakeWindowHandle> mSecondWindow;
8312
8313 void SetUp() override {
8314 InputDispatcherTest::SetUp();
8315 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008316 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008317 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008318 mSecondWindow =
8319 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008320 mSecondWindow->setFocusable(true);
8321
8322 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008323 mDispatcher->onWindowInfosChanged(
8324 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008325
8326 setFocusedWindow(mWindow);
8327 mWindow->consumeFocusEvent(true);
8328 }
8329
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008330 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008331 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008332 }
8333
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008334 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8335 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008336 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008337 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8338 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008339 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008340 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008341 }
8342};
8343
8344TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8345 // Ensure that capture cannot be obtained for unfocused windows.
8346 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8347 mFakePolicy->assertSetPointerCaptureNotCalled();
8348 mSecondWindow->assertNoEvents();
8349
8350 // Ensure that capture can be enabled from the focus window.
8351 requestAndVerifyPointerCapture(mWindow, true);
8352
8353 // Ensure that capture cannot be disabled from a window that does not have capture.
8354 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8355 mFakePolicy->assertSetPointerCaptureNotCalled();
8356
8357 // Ensure that capture can be disabled from the window with capture.
8358 requestAndVerifyPointerCapture(mWindow, false);
8359}
8360
8361TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008362 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008363
8364 setFocusedWindow(mSecondWindow);
8365
8366 // Ensure that the capture disabled event was sent first.
8367 mWindow->consumeCaptureEvent(false);
8368 mWindow->consumeFocusEvent(false);
8369 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008370 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008371
8372 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008373 notifyPointerCaptureChanged({});
8374 notifyPointerCaptureChanged(request);
8375 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008376 mWindow->assertNoEvents();
8377 mSecondWindow->assertNoEvents();
8378 mFakePolicy->assertSetPointerCaptureNotCalled();
8379}
8380
8381TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008382 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008383
8384 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008385 notifyPointerCaptureChanged({});
8386 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008387
8388 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008389 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008390 mWindow->consumeCaptureEvent(false);
8391 mWindow->assertNoEvents();
8392}
8393
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008394TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8395 requestAndVerifyPointerCapture(mWindow, true);
8396
8397 // The first window loses focus.
8398 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008399 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008400 mWindow->consumeCaptureEvent(false);
8401
8402 // Request Pointer Capture from the second window before the notification from InputReader
8403 // arrives.
8404 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008405 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008406
8407 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008408 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008409
8410 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008411 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008412
8413 mSecondWindow->consumeFocusEvent(true);
8414 mSecondWindow->consumeCaptureEvent(true);
8415}
8416
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008417TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8418 // App repeatedly enables and disables capture.
8419 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8420 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8421 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8422 mFakePolicy->assertSetPointerCaptureCalled(false);
8423 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8424 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8425
8426 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8427 // first request is now stale, this should do nothing.
8428 notifyPointerCaptureChanged(firstRequest);
8429 mWindow->assertNoEvents();
8430
8431 // InputReader notifies that the second request was enabled.
8432 notifyPointerCaptureChanged(secondRequest);
8433 mWindow->consumeCaptureEvent(true);
8434}
8435
Prabir Pradhan7092e262022-05-03 16:51:09 +00008436TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8437 requestAndVerifyPointerCapture(mWindow, true);
8438
8439 // App toggles pointer capture off and on.
8440 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8441 mFakePolicy->assertSetPointerCaptureCalled(false);
8442
8443 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8444 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8445
8446 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8447 // preceding "disable" request.
8448 notifyPointerCaptureChanged(enableRequest);
8449
8450 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8451 // any notifications.
8452 mWindow->assertNoEvents();
8453}
8454
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008455/**
8456 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8457 * mouse movements don't affect the previous mouse hovering state.
8458 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8459 * HOVER_MOVE events).
8460 */
8461TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8462 // Mouse hover on the window
8463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8464 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8465 .build());
8466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8467 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8468 .build());
8469
8470 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8471 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8472
8473 // Start pointer capture
8474 requestAndVerifyPointerCapture(mWindow, true);
8475
8476 // Send some relative mouse movements and receive them in the window.
8477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8479 .build());
8480 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8481 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8482
8483 // Stop pointer capture
8484 requestAndVerifyPointerCapture(mWindow, false);
8485
8486 // Continue hovering on the window
8487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8488 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8489 .build());
8490 mWindow->consumeMotionEvent(
8491 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8492
8493 mWindow->assertNoEvents();
8494}
8495
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008496class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8497protected:
8498 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008499
8500 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8501 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8502
8503 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8504 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8505
8506 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8507 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8508 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8509 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8510 MAXIMUM_OBSCURING_OPACITY);
8511
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008512 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8513 static constexpr gui::Uid APP_B_UID{10002};
8514 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008515
8516 sp<FakeWindowHandle> mTouchWindow;
8517
8518 virtual void SetUp() override {
8519 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008520 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008521 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8522 }
8523
8524 virtual void TearDown() override {
8525 InputDispatcherTest::TearDown();
8526 mTouchWindow.clear();
8527 }
8528
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008529 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008530 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008531 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008532 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008533 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008534 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008535 return window;
8536 }
8537
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008538 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008539 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8540 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008541 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008542 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008543 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008544 return window;
8545 }
8546
8547 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008548 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8549 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8550 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008551 }
8552};
8553
8554TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008555 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008556 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008557 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008558
8559 touch();
8560
8561 mTouchWindow->assertNoEvents();
8562}
8563
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008564TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008565 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8566 const sp<FakeWindowHandle>& w =
8567 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008568 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008569
8570 touch();
8571
8572 mTouchWindow->assertNoEvents();
8573}
8574
8575TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008576 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8577 const sp<FakeWindowHandle>& w =
8578 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008579 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008580
8581 touch();
8582
8583 w->assertNoEvents();
8584}
8585
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008586TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008587 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008588 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008589
8590 touch();
8591
8592 mTouchWindow->consumeAnyMotionDown();
8593}
8594
8595TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008596 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008597 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008598 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008599 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008600
8601 touch({PointF{100, 100}});
8602
8603 mTouchWindow->consumeAnyMotionDown();
8604}
8605
8606TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008607 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008608 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008609 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008610
8611 touch();
8612
8613 mTouchWindow->consumeAnyMotionDown();
8614}
8615
8616TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8617 const sp<FakeWindowHandle>& w =
8618 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008619 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008620
8621 touch();
8622
8623 mTouchWindow->consumeAnyMotionDown();
8624}
8625
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008626TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8627 const sp<FakeWindowHandle>& w =
8628 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008629 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008630
8631 touch();
8632
8633 w->assertNoEvents();
8634}
8635
8636/**
8637 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8638 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8639 * window, the occluding window will still receive ACTION_OUTSIDE event.
8640 */
8641TEST_F(InputDispatcherUntrustedTouchesTest,
8642 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8643 const sp<FakeWindowHandle>& w =
8644 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008645 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008646 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008647
8648 touch();
8649
8650 w->consumeMotionOutside();
8651}
8652
8653TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8654 const sp<FakeWindowHandle>& w =
8655 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008656 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008657 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008658
8659 touch();
8660
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008661 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008662}
8663
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008664TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008665 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008666 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8667 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008668 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008669
8670 touch();
8671
8672 mTouchWindow->consumeAnyMotionDown();
8673}
8674
8675TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8676 const sp<FakeWindowHandle>& w =
8677 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8678 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008679 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008680
8681 touch();
8682
8683 mTouchWindow->consumeAnyMotionDown();
8684}
8685
8686TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008687 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008688 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8689 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008690 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008691
8692 touch();
8693
8694 mTouchWindow->assertNoEvents();
8695}
8696
8697TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8698 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8699 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008700 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8701 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008702 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008703 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8704 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008705 mDispatcher->onWindowInfosChanged(
8706 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008707
8708 touch();
8709
8710 mTouchWindow->assertNoEvents();
8711}
8712
8713TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8714 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8715 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008716 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8717 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008718 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008719 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8720 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008721 mDispatcher->onWindowInfosChanged(
8722 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008723
8724 touch();
8725
8726 mTouchWindow->consumeAnyMotionDown();
8727}
8728
8729TEST_F(InputDispatcherUntrustedTouchesTest,
8730 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8731 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008732 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8733 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008734 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008735 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8736 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008737 mDispatcher->onWindowInfosChanged(
8738 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008739
8740 touch();
8741
8742 mTouchWindow->consumeAnyMotionDown();
8743}
8744
8745TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8746 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008747 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8748 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008749 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008750 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8751 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008752 mDispatcher->onWindowInfosChanged(
8753 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008754
8755 touch();
8756
8757 mTouchWindow->assertNoEvents();
8758}
8759
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008760TEST_F(InputDispatcherUntrustedTouchesTest,
8761 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8762 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008763 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8764 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008765 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008766 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8767 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008768 mDispatcher->onWindowInfosChanged(
8769 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008770
8771 touch();
8772
8773 mTouchWindow->assertNoEvents();
8774}
8775
8776TEST_F(InputDispatcherUntrustedTouchesTest,
8777 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8778 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008779 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8780 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008781 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008782 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8783 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008784 mDispatcher->onWindowInfosChanged(
8785 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008786
8787 touch();
8788
8789 mTouchWindow->consumeAnyMotionDown();
8790}
8791
8792TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8793 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008794 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8795 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008796 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008797
8798 touch();
8799
8800 mTouchWindow->consumeAnyMotionDown();
8801}
8802
8803TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8804 const sp<FakeWindowHandle>& w =
8805 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008806 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008807
8808 touch();
8809
8810 mTouchWindow->consumeAnyMotionDown();
8811}
8812
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008813TEST_F(InputDispatcherUntrustedTouchesTest,
8814 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8815 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8816 const sp<FakeWindowHandle>& w =
8817 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008818 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008819
8820 touch();
8821
8822 mTouchWindow->assertNoEvents();
8823}
8824
8825TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8826 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8827 const sp<FakeWindowHandle>& w =
8828 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008829 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008830
8831 touch();
8832
8833 mTouchWindow->consumeAnyMotionDown();
8834}
8835
8836TEST_F(InputDispatcherUntrustedTouchesTest,
8837 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8838 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8839 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008840 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8841 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008842 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008843
8844 touch();
8845
8846 mTouchWindow->consumeAnyMotionDown();
8847}
8848
8849TEST_F(InputDispatcherUntrustedTouchesTest,
8850 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8851 const sp<FakeWindowHandle>& w1 =
8852 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8853 OPACITY_BELOW_THRESHOLD);
8854 const sp<FakeWindowHandle>& w2 =
8855 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8856 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008857 mDispatcher->onWindowInfosChanged(
8858 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008859
8860 touch();
8861
8862 mTouchWindow->assertNoEvents();
8863}
8864
8865/**
8866 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8867 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8868 * (which alone would result in allowing touches) does not affect the blocking behavior.
8869 */
8870TEST_F(InputDispatcherUntrustedTouchesTest,
8871 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8872 const sp<FakeWindowHandle>& wB =
8873 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8874 OPACITY_BELOW_THRESHOLD);
8875 const sp<FakeWindowHandle>& wC =
8876 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8877 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008878 mDispatcher->onWindowInfosChanged(
8879 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008880
8881 touch();
8882
8883 mTouchWindow->assertNoEvents();
8884}
8885
8886/**
8887 * This test is testing that a window from a different UID but with same application token doesn't
8888 * block the touch. Apps can share the application token for close UI collaboration for example.
8889 */
8890TEST_F(InputDispatcherUntrustedTouchesTest,
8891 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8892 const sp<FakeWindowHandle>& w =
8893 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8894 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008895 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008896
8897 touch();
8898
8899 mTouchWindow->consumeAnyMotionDown();
8900}
8901
arthurhungb89ccb02020-12-30 16:19:01 +08008902class InputDispatcherDragTests : public InputDispatcherTest {
8903protected:
8904 std::shared_ptr<FakeApplicationHandle> mApp;
8905 sp<FakeWindowHandle> mWindow;
8906 sp<FakeWindowHandle> mSecondWindow;
8907 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008908 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008909 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8910 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008911
8912 void SetUp() override {
8913 InputDispatcherTest::SetUp();
8914 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008915 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008916 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008917
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008918 mSecondWindow =
8919 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008920 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008921
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008922 mSpyWindow =
8923 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008924 mSpyWindow->setSpy(true);
8925 mSpyWindow->setTrustedOverlay(true);
8926 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8927
arthurhungb89ccb02020-12-30 16:19:01 +08008928 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008929 mDispatcher->onWindowInfosChanged(
8930 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8931 {},
8932 0,
8933 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008934 }
8935
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008936 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8937 switch (fromSource) {
8938 case AINPUT_SOURCE_TOUCHSCREEN:
8939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008940 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008941 ADISPLAY_ID_DEFAULT, {50, 50}))
8942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8943 break;
8944 case AINPUT_SOURCE_STYLUS:
8945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008946 injectMotionEvent(*mDispatcher,
8947 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8948 AINPUT_SOURCE_STYLUS)
8949 .buttonState(
8950 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8951 .pointer(PointerBuilder(0, ToolType::STYLUS)
8952 .x(50)
8953 .y(50))
8954 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008955 break;
8956 case AINPUT_SOURCE_MOUSE:
8957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008958 injectMotionEvent(*mDispatcher,
8959 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8960 AINPUT_SOURCE_MOUSE)
8961 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8962 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8963 ToolType::MOUSE)
8964 .x(50)
8965 .y(50))
8966 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008967 break;
8968 default:
8969 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8970 }
arthurhungb89ccb02020-12-30 16:19:01 +08008971
8972 // Window should receive motion event.
8973 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008974 // Spy window should also receive motion event
8975 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008976 }
8977
8978 // Start performing drag, we will create a drag window and transfer touch to it.
8979 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8980 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008981 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008982 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008983 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008984 }
arthurhungb89ccb02020-12-30 16:19:01 +08008985
8986 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008987 mDragWindow =
8988 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008989 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008990 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8991 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8992 {},
8993 0,
8994 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008995
8996 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008997 bool transferred =
8998 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008999 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009000 if (transferred) {
9001 mWindow->consumeMotionCancel();
9002 mDragWindow->consumeMotionDown();
9003 }
9004 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009005 }
9006};
9007
9008TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009009 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009010
9011 // Move on window.
9012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009013 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009014 ADISPLAY_ID_DEFAULT, {50, 50}))
9015 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9016 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9017 mWindow->consumeDragEvent(false, 50, 50);
9018 mSecondWindow->assertNoEvents();
9019
9020 // Move to another window.
9021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009022 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009023 ADISPLAY_ID_DEFAULT, {150, 50}))
9024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9025 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9026 mWindow->consumeDragEvent(true, 150, 50);
9027 mSecondWindow->consumeDragEvent(false, 50, 50);
9028
9029 // Move back to original window.
9030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009031 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009032 ADISPLAY_ID_DEFAULT, {50, 50}))
9033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9034 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9035 mWindow->consumeDragEvent(false, 50, 50);
9036 mSecondWindow->consumeDragEvent(true, -50, 50);
9037
9038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009039 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9040 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9042 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9043 mWindow->assertNoEvents();
9044 mSecondWindow->assertNoEvents();
9045}
9046
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009047TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009048 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009049
9050 // No cancel event after drag start
9051 mSpyWindow->assertNoEvents();
9052
9053 const MotionEvent secondFingerDownEvent =
9054 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9055 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009056 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9057 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009058 .build();
9059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009060 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009061 InputEventInjectionSync::WAIT_FOR_RESULT))
9062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9063
9064 // Receives cancel for first pointer after next pointer down
9065 mSpyWindow->consumeMotionCancel();
9066 mSpyWindow->consumeMotionDown();
9067
9068 mSpyWindow->assertNoEvents();
9069}
9070
arthurhungf452d0b2021-01-06 00:19:52 +08009071TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009072 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009073
9074 // Move on window.
9075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009076 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009077 ADISPLAY_ID_DEFAULT, {50, 50}))
9078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9079 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9080 mWindow->consumeDragEvent(false, 50, 50);
9081 mSecondWindow->assertNoEvents();
9082
9083 // Move to another window.
9084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009085 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009086 ADISPLAY_ID_DEFAULT, {150, 50}))
9087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9088 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9089 mWindow->consumeDragEvent(true, 150, 50);
9090 mSecondWindow->consumeDragEvent(false, 50, 50);
9091
9092 // drop to another window.
9093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009094 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009095 {150, 50}))
9096 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9097 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009098 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009099 mWindow->assertNoEvents();
9100 mSecondWindow->assertNoEvents();
9101}
9102
arthurhung6d4bed92021-03-17 11:59:33 +08009103TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009104 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009105
9106 // Move on window and keep button pressed.
9107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009108 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009109 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9110 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009111 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009112 .build()))
9113 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9114 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9115 mWindow->consumeDragEvent(false, 50, 50);
9116 mSecondWindow->assertNoEvents();
9117
9118 // Move to another window and release button, expect to drop item.
9119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009120 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009121 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9122 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009123 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009124 .build()))
9125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9126 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9127 mWindow->assertNoEvents();
9128 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009129 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009130
9131 // nothing to the window.
9132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009133 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009134 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9135 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009136 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009137 .build()))
9138 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9139 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9140 mWindow->assertNoEvents();
9141 mSecondWindow->assertNoEvents();
9142}
9143
Arthur Hung54745652022-04-20 07:17:41 +00009144TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009145 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009146
9147 // Set second window invisible.
9148 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009149 mDispatcher->onWindowInfosChanged(
9150 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009151
9152 // Move on window.
9153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009154 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009155 ADISPLAY_ID_DEFAULT, {50, 50}))
9156 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9157 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9158 mWindow->consumeDragEvent(false, 50, 50);
9159 mSecondWindow->assertNoEvents();
9160
9161 // Move to another window.
9162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009163 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009164 ADISPLAY_ID_DEFAULT, {150, 50}))
9165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9166 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9167 mWindow->consumeDragEvent(true, 150, 50);
9168 mSecondWindow->assertNoEvents();
9169
9170 // drop to another window.
9171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009172 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009173 {150, 50}))
9174 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9175 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009176 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009177 mWindow->assertNoEvents();
9178 mSecondWindow->assertNoEvents();
9179}
9180
Arthur Hung54745652022-04-20 07:17:41 +00009181TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009182 // Ensure window could track pointerIds if it didn't support split touch.
9183 mWindow->setPreventSplitting(true);
9184
Arthur Hung54745652022-04-20 07:17:41 +00009185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009186 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009187 {50, 50}))
9188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9189 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9190
9191 const MotionEvent secondFingerDownEvent =
9192 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9193 .displayId(ADISPLAY_ID_DEFAULT)
9194 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009195 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9196 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009197 .build();
9198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009199 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009200 InputEventInjectionSync::WAIT_FOR_RESULT))
9201 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009202 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009203
9204 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009205 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009206}
9207
9208TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9209 // First down on second window.
9210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009211 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009212 {150, 50}))
9213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9214
9215 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9216
9217 // Second down on first window.
9218 const MotionEvent secondFingerDownEvent =
9219 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9220 .displayId(ADISPLAY_ID_DEFAULT)
9221 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009222 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9223 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009224 .build();
9225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009226 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009227 InputEventInjectionSync::WAIT_FOR_RESULT))
9228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9229 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9230
9231 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009232 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009233
9234 // Move on window.
9235 const MotionEvent secondFingerMoveEvent =
9236 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9237 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009238 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9239 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009240 .build();
9241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009242 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009243 InputEventInjectionSync::WAIT_FOR_RESULT));
9244 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9245 mWindow->consumeDragEvent(false, 50, 50);
9246 mSecondWindow->consumeMotionMove();
9247
9248 // Release the drag pointer should perform drop.
9249 const MotionEvent secondFingerUpEvent =
9250 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9251 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009252 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9253 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009254 .build();
9255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009256 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009257 InputEventInjectionSync::WAIT_FOR_RESULT));
9258 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009259 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009260 mWindow->assertNoEvents();
9261 mSecondWindow->consumeMotionMove();
9262}
9263
Arthur Hung3915c1f2022-05-31 07:17:17 +00009264TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009265 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009266
9267 // Update window of second display.
9268 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009269 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009270 mDispatcher->onWindowInfosChanged(
9271 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9272 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9273 {},
9274 0,
9275 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009276
9277 // Let second display has a touch state.
9278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009279 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009280 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9281 AINPUT_SOURCE_TOUCHSCREEN)
9282 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009283 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009284 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009285 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009286 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009287 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009288 mDispatcher->onWindowInfosChanged(
9289 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9290 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9291 {},
9292 0,
9293 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009294
9295 // Move on window.
9296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009297 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009298 ADISPLAY_ID_DEFAULT, {50, 50}))
9299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9300 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9301 mWindow->consumeDragEvent(false, 50, 50);
9302 mSecondWindow->assertNoEvents();
9303
9304 // Move to another window.
9305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009306 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009307 ADISPLAY_ID_DEFAULT, {150, 50}))
9308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9309 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9310 mWindow->consumeDragEvent(true, 150, 50);
9311 mSecondWindow->consumeDragEvent(false, 50, 50);
9312
9313 // drop to another window.
9314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009315 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009316 {150, 50}))
9317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9318 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009319 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009320 mWindow->assertNoEvents();
9321 mSecondWindow->assertNoEvents();
9322}
9323
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009324TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9325 startDrag(true, AINPUT_SOURCE_MOUSE);
9326 // Move on window.
9327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009328 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009329 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9330 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009331 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009332 .x(50)
9333 .y(50))
9334 .build()))
9335 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9336 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9337 mWindow->consumeDragEvent(false, 50, 50);
9338 mSecondWindow->assertNoEvents();
9339
9340 // Move to another window.
9341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009342 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009343 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9344 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009345 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009346 .x(150)
9347 .y(50))
9348 .build()))
9349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9350 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9351 mWindow->consumeDragEvent(true, 150, 50);
9352 mSecondWindow->consumeDragEvent(false, 50, 50);
9353
9354 // drop to another window.
9355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009356 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009357 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9358 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009359 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009360 .x(150)
9361 .y(50))
9362 .build()))
9363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9364 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009365 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009366 mWindow->assertNoEvents();
9367 mSecondWindow->assertNoEvents();
9368}
9369
Linnan Li5af92f92023-07-14 14:36:22 +08009370/**
9371 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9372 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9373 */
9374TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9375 // Down on second window
9376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9377 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9378 {150, 50}))
9379 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9380
9381 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9382 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9383
9384 // Down on first window
9385 const MotionEvent secondFingerDownEvent =
9386 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9387 .displayId(ADISPLAY_ID_DEFAULT)
9388 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9389 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9390 .build();
9391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9392 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9393 InputEventInjectionSync::WAIT_FOR_RESULT))
9394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9395 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9396 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9397 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9398
9399 // Start drag on first window
9400 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9401
9402 // Trigger cancel
9403 mDispatcher->cancelCurrentTouch();
9404 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9405 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9406 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9407
9408 ASSERT_TRUE(mDispatcher->waitForIdle());
9409 // The D&D finished with nullptr
9410 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9411
9412 // Remove drag window
9413 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9414
9415 // Inject a simple gesture, ensure dispatcher not crashed
9416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9417 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9418 PointF{50, 50}))
9419 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9420 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9421
9422 const MotionEvent moveEvent =
9423 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9424 .displayId(ADISPLAY_ID_DEFAULT)
9425 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9426 .build();
9427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9428 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9429 InputEventInjectionSync::WAIT_FOR_RESULT))
9430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9431 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9432
9433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9434 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9435 {50, 50}))
9436 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9437 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9438}
9439
Vishnu Nair062a8672021-09-03 16:07:44 -07009440class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9441
9442TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009444 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9445 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009446 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009447 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9448 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009449 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009450 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009451 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009452
9453 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009454 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009455 window->assertNoEvents();
9456
Prabir Pradhan678438e2023-04-13 19:32:51 +00009457 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9458 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009459 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9460 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009461 window->assertNoEvents();
9462
9463 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009464 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009465 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009466
Prabir Pradhan678438e2023-04-13 19:32:51 +00009467 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009468 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9469
Prabir Pradhan678438e2023-04-13 19:32:51 +00009470 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9471 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009472 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9473 window->assertNoEvents();
9474}
9475
9476TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9477 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9478 std::make_shared<FakeApplicationHandle>();
9479 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009480 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9481 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009482 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009483 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009484 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009486 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9487 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009488 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009489 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009490 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9491 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009492 mDispatcher->onWindowInfosChanged(
9493 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009494 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009495 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009496
9497 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009498 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009499 window->assertNoEvents();
9500
Prabir Pradhan678438e2023-04-13 19:32:51 +00009501 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9502 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009503 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9504 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009505 window->assertNoEvents();
9506
9507 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009508 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009509 mDispatcher->onWindowInfosChanged(
9510 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009511
Prabir Pradhan678438e2023-04-13 19:32:51 +00009512 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009513 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9514
Prabir Pradhan678438e2023-04-13 19:32:51 +00009515 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9516 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009517 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9518 window->assertNoEvents();
9519}
9520
9521TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9522 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9523 std::make_shared<FakeApplicationHandle>();
9524 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009525 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9526 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009527 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009528 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009529 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009530 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009531 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9532 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009533 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009534 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009535 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9536 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009537 mDispatcher->onWindowInfosChanged(
9538 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009539 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009540 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009541
9542 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009543 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009544 window->assertNoEvents();
9545
Prabir Pradhan678438e2023-04-13 19:32:51 +00009546 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9547 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009548 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9549 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009550 window->assertNoEvents();
9551
9552 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009553 mDispatcher->onWindowInfosChanged(
9554 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009555
Prabir Pradhan678438e2023-04-13 19:32:51 +00009556 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009557 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9558
Prabir Pradhan678438e2023-04-13 19:32:51 +00009559 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9560 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009561 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9562 window->assertNoEvents();
9563}
9564
Antonio Kantekf16f2832021-09-28 04:39:20 +00009565class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9566protected:
9567 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009568 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009569 sp<FakeWindowHandle> mWindow;
9570 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009571 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009572
9573 void SetUp() override {
9574 InputDispatcherTest::SetUp();
9575
9576 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009577 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009578 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009579 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009580 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009581 mSecondWindow =
9582 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009583 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009584 mThirdWindow =
9585 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9586 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9587 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009588
9589 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009590 mDispatcher->onWindowInfosChanged(
9591 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9592 {},
9593 0,
9594 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009595 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009596 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009597
Antonio Kantek15beb512022-06-13 22:35:41 +00009598 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009599 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009600 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009601 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9602 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009603 mThirdWindow->assertNoEvents();
9604 }
9605
9606 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9607 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009608 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009609 SECOND_DISPLAY_ID)) {
9610 mWindow->assertNoEvents();
9611 mSecondWindow->assertNoEvents();
9612 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009613 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009614 }
9615
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009616 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009617 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009618 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9619 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009620 mWindow->consumeTouchModeEvent(inTouchMode);
9621 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009622 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009623 }
9624};
9625
Antonio Kantek26defcf2022-02-08 01:12:27 +00009626TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009627 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009628 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9629 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009630 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009631}
9632
Antonio Kantek26defcf2022-02-08 01:12:27 +00009633TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9634 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009635 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009636 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009637 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009638 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009639 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009640 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009641 mWindow->assertNoEvents();
9642 mSecondWindow->assertNoEvents();
9643}
9644
9645TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9646 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009647 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009648 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009649 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009650 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009651 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009652}
9653
Antonio Kantekf16f2832021-09-28 04:39:20 +00009654TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009655 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009656 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9657 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009658 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009659 mWindow->assertNoEvents();
9660 mSecondWindow->assertNoEvents();
9661}
9662
Antonio Kantek15beb512022-06-13 22:35:41 +00009663TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9664 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9665 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9666 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009667 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009668 mWindow->assertNoEvents();
9669 mSecondWindow->assertNoEvents();
9670 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9671}
9672
Antonio Kantek48710e42022-03-24 14:19:30 -07009673TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9674 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9676 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009677 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9678 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9679
9680 // Then remove focus.
9681 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009682 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009683
9684 // Assert that caller can switch touch mode by owning one of the last interacted window.
9685 const WindowInfo& windowInfo = *mWindow->getInfo();
9686 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9687 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009688 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009689}
9690
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009691class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9692public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009693 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009694 std::shared_ptr<FakeApplicationHandle> application =
9695 std::make_shared<FakeApplicationHandle>();
9696 std::string name = "Fake Spy ";
9697 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009698 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9699 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009700 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009701 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009702 return spy;
9703 }
9704
9705 sp<FakeWindowHandle> createForeground() {
9706 std::shared_ptr<FakeApplicationHandle> application =
9707 std::make_shared<FakeApplicationHandle>();
9708 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009709 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9710 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009711 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009712 return window;
9713 }
9714
9715private:
9716 int mSpyCount{0};
9717};
9718
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009719using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009720/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009721 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9722 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009723TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009724 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009725 ScopedSilentDeath _silentDeath;
9726
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009727 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009728 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009729 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009730 ".* not a trusted overlay");
9731}
9732
9733/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009734 * Input injection into a display with a spy window but no foreground windows should succeed.
9735 */
9736TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009737 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009738 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009739
9740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009741 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9743 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9744}
9745
9746/**
9747 * Verify the order in which different input windows receive events. The touched foreground window
9748 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9749 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9750 * receive events before ones belows it.
9751 *
9752 * Here, we set up a scenario with four windows in the following Z order from the top:
9753 * spy1, spy2, window, spy3.
9754 * We then inject an event and verify that the foreground "window" receives it first, followed by
9755 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9756 * window.
9757 */
9758TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9759 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009760 auto spy1 = createSpy();
9761 auto spy2 = createSpy();
9762 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009763 mDispatcher->onWindowInfosChanged(
9764 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009765 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9766 const size_t numChannels = channels.size();
9767
Michael Wright8e9a8562022-02-09 13:44:29 +00009768 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009769 if (!epollFd.ok()) {
9770 FAIL() << "Failed to create epoll fd";
9771 }
9772
9773 for (size_t i = 0; i < numChannels; i++) {
9774 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9775 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9776 FAIL() << "Failed to add fd to epoll";
9777 }
9778 }
9779
9780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009781 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9783
9784 std::vector<size_t> eventOrder;
9785 std::vector<struct epoll_event> events(numChannels);
9786 for (;;) {
9787 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9788 (100ms).count());
9789 if (nFds < 0) {
9790 FAIL() << "Failed to call epoll_wait";
9791 }
9792 if (nFds == 0) {
9793 break; // epoll_wait timed out
9794 }
9795 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009796 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009797 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009798 channels[i]->consumeMotionDown();
9799 }
9800 }
9801
9802 // Verify the order in which the events were received.
9803 EXPECT_EQ(3u, eventOrder.size());
9804 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9805 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9806 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9807}
9808
9809/**
9810 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9811 */
9812TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9813 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009814 auto spy = createSpy();
9815 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009816 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009817
9818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009819 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9821 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9822 spy->assertNoEvents();
9823}
9824
9825/**
9826 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9827 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9828 * to the window.
9829 */
9830TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9831 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009832 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009833 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009834 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009835
9836 // Inject an event outside the spy window's touchable region.
9837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009838 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9840 window->consumeMotionDown();
9841 spy->assertNoEvents();
9842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009843 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009844 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9845 window->consumeMotionUp();
9846 spy->assertNoEvents();
9847
9848 // Inject an event inside the spy window's touchable region.
9849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009850 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009851 {5, 10}))
9852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9853 window->consumeMotionDown();
9854 spy->consumeMotionDown();
9855}
9856
9857/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009858 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009859 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009860 */
9861TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9862 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009863 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009864 auto spy = createSpy();
9865 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009866 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009867 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009868 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009869
9870 // Inject an event outside the spy window's frame and touchable region.
9871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009872 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009873 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9875 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009876 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009877}
9878
9879/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009880 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9881 * pointers that are down within its bounds.
9882 */
9883TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9884 auto windowLeft = createForeground();
9885 windowLeft->setFrame({0, 0, 100, 200});
9886 auto windowRight = createForeground();
9887 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009888 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009889 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009890 mDispatcher->onWindowInfosChanged(
9891 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009892
9893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009894 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009895 {50, 50}))
9896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9897 windowLeft->consumeMotionDown();
9898 spy->consumeMotionDown();
9899
9900 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009901 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009902 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009903 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9904 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009905 .build();
9906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009907 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009908 InputEventInjectionSync::WAIT_FOR_RESULT))
9909 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9910 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009911 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009912}
9913
9914/**
9915 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9916 * the spy should receive the second pointer with ACTION_DOWN.
9917 */
9918TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9919 auto window = createForeground();
9920 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009921 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009922 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009923 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009924
9925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009926 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009927 {50, 50}))
9928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9929 window->consumeMotionDown();
9930 spyRight->assertNoEvents();
9931
9932 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009933 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009934 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009935 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9936 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009937 .build();
9938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009939 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009940 InputEventInjectionSync::WAIT_FOR_RESULT))
9941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009942 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009943 spyRight->consumeMotionDown();
9944}
9945
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009946/**
9947 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9948 * windows should be allowed to control split touch.
9949 */
9950TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009951 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009952 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009953 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009954 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009955
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009956 auto window = createForeground();
9957 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009958
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009959 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009960
9961 // First finger down, no window touched.
9962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009963 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009964 {100, 200}))
9965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9966 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9967 window->assertNoEvents();
9968
9969 // Second finger down on window, the window should receive touch down.
9970 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009971 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009972 .displayId(ADISPLAY_ID_DEFAULT)
9973 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009974 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9975 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009976 .build();
9977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009978 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009979 InputEventInjectionSync::WAIT_FOR_RESULT))
9980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9981
9982 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009983 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009984}
9985
9986/**
9987 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9988 * do not receive key events.
9989 */
9990TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009991 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009992 spy->setFocusable(false);
9993
9994 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009995 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009996 setFocusedWindow(window);
9997 window->consumeFocusEvent(true);
9998
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010000 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10001 window->consumeKeyDown(ADISPLAY_ID_NONE);
10002
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010004 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10005 window->consumeKeyUp(ADISPLAY_ID_NONE);
10006
10007 spy->assertNoEvents();
10008}
10009
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010010using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10011
10012/**
10013 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10014 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10015 */
10016TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10017 auto window = createForeground();
10018 auto spy1 = createSpy();
10019 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010020 mDispatcher->onWindowInfosChanged(
10021 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010022
10023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010024 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10026 window->consumeMotionDown();
10027 spy1->consumeMotionDown();
10028 spy2->consumeMotionDown();
10029
10030 // Pilfer pointers from the second spy window.
10031 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10032 spy2->assertNoEvents();
10033 spy1->consumeMotionCancel();
10034 window->consumeMotionCancel();
10035
10036 // The rest of the gesture should only be sent to the second spy window.
10037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010038 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010039 ADISPLAY_ID_DEFAULT))
10040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10041 spy2->consumeMotionMove();
10042 spy1->assertNoEvents();
10043 window->assertNoEvents();
10044}
10045
10046/**
10047 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10048 * in the middle of the gesture.
10049 */
10050TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10051 auto window = createForeground();
10052 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010053 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010054
10055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010056 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10058 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10059 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10060
10061 window->releaseChannel();
10062
10063 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10064
10065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010066 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10068 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10069}
10070
10071/**
10072 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10073 * the spy, but not to any other windows.
10074 */
10075TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10076 auto spy = createSpy();
10077 auto window = createForeground();
10078
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010079 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010080
10081 // First finger down on the window and the spy.
10082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010083 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010084 {100, 200}))
10085 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10086 spy->consumeMotionDown();
10087 window->consumeMotionDown();
10088
10089 // Spy window pilfers the pointers.
10090 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10091 window->consumeMotionCancel();
10092
10093 // Second finger down on the window and spy, but the window should not receive the pointer down.
10094 const MotionEvent secondFingerDownEvent =
10095 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10096 .displayId(ADISPLAY_ID_DEFAULT)
10097 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010098 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10099 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010100 .build();
10101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010102 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010103 InputEventInjectionSync::WAIT_FOR_RESULT))
10104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10105
Harry Cutts33476232023-01-30 19:57:29 +000010106 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010107
10108 // Third finger goes down outside all windows, so injection should fail.
10109 const MotionEvent thirdFingerDownEvent =
10110 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10111 .displayId(ADISPLAY_ID_DEFAULT)
10112 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010113 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10114 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10115 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010116 .build();
10117 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010118 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010119 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010120 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010121
10122 spy->assertNoEvents();
10123 window->assertNoEvents();
10124}
10125
10126/**
10127 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10128 */
10129TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10130 auto spy = createSpy();
10131 spy->setFrame(Rect(0, 0, 100, 100));
10132 auto window = createForeground();
10133 window->setFrame(Rect(0, 0, 200, 200));
10134
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010135 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010136
10137 // First finger down on the window only
10138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010139 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010140 {150, 150}))
10141 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10142 window->consumeMotionDown();
10143
10144 // Second finger down on the spy and window
10145 const MotionEvent secondFingerDownEvent =
10146 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10147 .displayId(ADISPLAY_ID_DEFAULT)
10148 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010149 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10150 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010151 .build();
10152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010153 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010154 InputEventInjectionSync::WAIT_FOR_RESULT))
10155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10156 spy->consumeMotionDown();
10157 window->consumeMotionPointerDown(1);
10158
10159 // Third finger down on the spy and window
10160 const MotionEvent thirdFingerDownEvent =
10161 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10162 .displayId(ADISPLAY_ID_DEFAULT)
10163 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010164 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10165 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10166 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010167 .build();
10168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010169 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010170 InputEventInjectionSync::WAIT_FOR_RESULT))
10171 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10172 spy->consumeMotionPointerDown(1);
10173 window->consumeMotionPointerDown(2);
10174
10175 // Spy window pilfers the pointers.
10176 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010177 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10178 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010179
10180 spy->assertNoEvents();
10181 window->assertNoEvents();
10182}
10183
10184/**
10185 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10186 * other windows should be canceled. If this results in the cancellation of all pointers for some
10187 * window, then that window should receive ACTION_CANCEL.
10188 */
10189TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10190 auto spy = createSpy();
10191 spy->setFrame(Rect(0, 0, 100, 100));
10192 auto window = createForeground();
10193 window->setFrame(Rect(0, 0, 200, 200));
10194
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010195 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010196
10197 // First finger down on both spy and window
10198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010199 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010200 {10, 10}))
10201 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10202 window->consumeMotionDown();
10203 spy->consumeMotionDown();
10204
10205 // Second finger down on the spy and window
10206 const MotionEvent secondFingerDownEvent =
10207 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10208 .displayId(ADISPLAY_ID_DEFAULT)
10209 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010210 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10211 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010212 .build();
10213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010214 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010215 InputEventInjectionSync::WAIT_FOR_RESULT))
10216 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10217 spy->consumeMotionPointerDown(1);
10218 window->consumeMotionPointerDown(1);
10219
10220 // Spy window pilfers the pointers.
10221 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10222 window->consumeMotionCancel();
10223
10224 spy->assertNoEvents();
10225 window->assertNoEvents();
10226}
10227
10228/**
10229 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10230 * be sent to other windows
10231 */
10232TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10233 auto spy = createSpy();
10234 spy->setFrame(Rect(0, 0, 100, 100));
10235 auto window = createForeground();
10236 window->setFrame(Rect(0, 0, 200, 200));
10237
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010238 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010239
10240 // First finger down on both window and spy
10241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010242 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010243 {10, 10}))
10244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10245 window->consumeMotionDown();
10246 spy->consumeMotionDown();
10247
10248 // Spy window pilfers the pointers.
10249 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10250 window->consumeMotionCancel();
10251
10252 // Second finger down on the window only
10253 const MotionEvent secondFingerDownEvent =
10254 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10255 .displayId(ADISPLAY_ID_DEFAULT)
10256 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010257 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10258 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010259 .build();
10260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010261 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010262 InputEventInjectionSync::WAIT_FOR_RESULT))
10263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10264 window->consumeMotionDown();
10265 window->assertNoEvents();
10266
10267 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10268 spy->consumeMotionMove();
10269 spy->assertNoEvents();
10270}
10271
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010272/**
10273 * A window on the left and a window on the right. Also, a spy window that's above all of the
10274 * windows, and spanning both left and right windows.
10275 * Send simultaneous motion streams from two different devices, one to the left window, and another
10276 * to the right window.
10277 * Pilfer from spy window.
10278 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10279 */
10280TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10281 sp<FakeWindowHandle> spy = createSpy();
10282 spy->setFrame(Rect(0, 0, 200, 200));
10283 sp<FakeWindowHandle> leftWindow = createForeground();
10284 leftWindow->setFrame(Rect(0, 0, 100, 100));
10285
10286 sp<FakeWindowHandle> rightWindow = createForeground();
10287 rightWindow->setFrame(Rect(100, 0, 200, 100));
10288
10289 constexpr int32_t stylusDeviceId = 1;
10290 constexpr int32_t touchDeviceId = 2;
10291
10292 mDispatcher->onWindowInfosChanged(
10293 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10294
10295 // Stylus down on left window and spy
10296 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10297 .deviceId(stylusDeviceId)
10298 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10299 .build());
10300 leftWindow->consumeMotionEvent(
10301 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10302 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10303
10304 // Finger down on right window and spy - but spy already has stylus
10305 mDispatcher->notifyMotion(
10306 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10307 .deviceId(touchDeviceId)
10308 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10309 .build());
10310 rightWindow->consumeMotionEvent(
10311 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10312 leftWindow->consumeMotionEvent(
10313 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10314 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10315 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10316
10317 // Act: pilfer from spy. Spy is currently receiving touch events.
10318 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10319 rightWindow->consumeMotionEvent(
10320 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10321
10322 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10323 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10324 .deviceId(stylusDeviceId)
10325 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10326 .build());
10327 mDispatcher->notifyMotion(
10328 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10329 .deviceId(touchDeviceId)
10330 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10331 .build());
10332 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10333
10334 spy->assertNoEvents();
10335 leftWindow->assertNoEvents();
10336 rightWindow->assertNoEvents();
10337}
10338
Prabir Pradhand65552b2021-10-07 11:23:50 -070010339class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10340public:
10341 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10342 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10343 std::make_shared<FakeApplicationHandle>();
10344 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010345 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10346 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010347 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010348 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010349 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010350 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010351 overlay->setTrustedOverlay(true);
10352
10353 std::shared_ptr<FakeApplicationHandle> application =
10354 std::make_shared<FakeApplicationHandle>();
10355 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010356 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10357 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010358 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010359 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010360
10361 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010362 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010363 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010364 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010365 return {std::move(overlay), std::move(window)};
10366 }
10367
10368 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010369 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010370 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010371 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010372 }
10373
10374 void sendStylusEvent(int32_t action) {
10375 NotifyMotionArgs motionArgs =
10376 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10377 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010378 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010379 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010380 }
10381};
10382
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010383using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10384
10385TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010386 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010387 ScopedSilentDeath _silentDeath;
10388
Prabir Pradhand65552b2021-10-07 11:23:50 -070010389 auto [overlay, window] = setupStylusOverlayScenario();
10390 overlay->setTrustedOverlay(false);
10391 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010392 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10393 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010394 ".* not a trusted overlay");
10395}
10396
10397TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10398 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010399 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010400
10401 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10402 overlay->consumeMotionDown();
10403 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10404 overlay->consumeMotionUp();
10405
10406 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10407 window->consumeMotionDown();
10408 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10409 window->consumeMotionUp();
10410
10411 overlay->assertNoEvents();
10412 window->assertNoEvents();
10413}
10414
10415TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10416 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010417 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010418 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010419
10420 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10421 overlay->consumeMotionDown();
10422 window->consumeMotionDown();
10423 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10424 overlay->consumeMotionUp();
10425 window->consumeMotionUp();
10426
10427 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10428 window->consumeMotionDown();
10429 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10430 window->consumeMotionUp();
10431
10432 overlay->assertNoEvents();
10433 window->assertNoEvents();
10434}
10435
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010436/**
10437 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10438 * The scenario is as follows:
10439 * - The stylus interceptor overlay is configured as a spy window.
10440 * - The stylus interceptor spy receives the start of a new stylus gesture.
10441 * - It pilfers pointers and then configures itself to no longer be a spy.
10442 * - The stylus interceptor continues to receive the rest of the gesture.
10443 */
10444TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10445 auto [overlay, window] = setupStylusOverlayScenario();
10446 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010447 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010448
10449 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10450 overlay->consumeMotionDown();
10451 window->consumeMotionDown();
10452
10453 // The interceptor pilfers the pointers.
10454 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10455 window->consumeMotionCancel();
10456
10457 // The interceptor configures itself so that it is no longer a spy.
10458 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010459 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010460
10461 // It continues to receive the rest of the stylus gesture.
10462 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10463 overlay->consumeMotionMove();
10464 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10465 overlay->consumeMotionUp();
10466
10467 window->assertNoEvents();
10468}
10469
Prabir Pradhan5735a322022-04-11 17:23:34 +000010470struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010471 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010472 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010473 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10474 std::unique_ptr<InputDispatcher>& mDispatcher;
10475
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010476 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010477 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10478
10479 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010480 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010481 ADISPLAY_ID_DEFAULT, {100, 200},
10482 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10483 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10484 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10485 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10486 }
10487
10488 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010489 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010490 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010491 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010492 mPolicyFlags);
10493 }
10494
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010495 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010496 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10497 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010498 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10499 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010500 window->setOwnerInfo(mPid, mUid);
10501 return window;
10502 }
10503};
10504
10505using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10506
10507TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010508 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010509 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010511
10512 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10513 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10514 window->consumeMotionDown();
10515
10516 setFocusedWindow(window);
10517 window->consumeFocusEvent(true);
10518
10519 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10520 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10521 window->consumeKeyDown(ADISPLAY_ID_NONE);
10522}
10523
10524TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010525 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010526 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010528
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010529 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010530 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10531 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10532
10533 setFocusedWindow(window);
10534 window->consumeFocusEvent(true);
10535
10536 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10537 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10538 window->assertNoEvents();
10539}
10540
10541TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010542 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010543 auto window = owner.createWindow("Owned window");
10544 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010545 spy->setSpy(true);
10546 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010547 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010548
10549 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10550 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10551 spy->consumeMotionDown();
10552 window->consumeMotionDown();
10553}
10554
10555TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
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");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010558
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010559 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010560 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010561 randosSpy->setSpy(true);
10562 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010563 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010564
10565 // The event is targeted at owner's window, so injection should succeed, but the spy should
10566 // not receive the event.
10567 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10568 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10569 randosSpy->assertNoEvents();
10570 window->consumeMotionDown();
10571}
10572
10573TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010574 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010575 auto window = owner.createWindow("Owned window");
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});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010578 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010579 randosSpy->setSpy(true);
10580 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010581 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010582
10583 // A user that has injection permission can inject into any window.
10584 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010585 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010586 ADISPLAY_ID_DEFAULT));
10587 randosSpy->consumeMotionDown();
10588 window->consumeMotionDown();
10589
10590 setFocusedWindow(randosSpy);
10591 randosSpy->consumeFocusEvent(true);
10592
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010593 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010594 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10595 window->assertNoEvents();
10596}
10597
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010598TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010599 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010600 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010601
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010602 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010603 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010604 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10605 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010606 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010607
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010608 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010609 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10610 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10611 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010612 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010613}
10614
Garfield Tane84e6f92019-08-29 17:28:41 -070010615} // namespace android::inputdispatcher