blob: 703c3f74cd08ff2f4d6a77996feb7dd5891e697d [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
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001454static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001455 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001456 int32_t displayId = ADISPLAY_ID_NONE,
1457 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001458 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001459 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001460 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001461 KeyEvent event;
1462 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1463
1464 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001465 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001466 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1467 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001468
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001469 if (!allowKeyRepeat) {
1470 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1471 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001472 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001473 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001474}
1475
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001476static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1477 InputEventInjectionResult result =
1478 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1479 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1480 if (result != InputEventInjectionResult::TIMED_OUT) {
1481 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1482 }
1483}
1484
1485static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001486 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001487 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001488}
1489
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001490// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1491// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1492// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001493static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1494 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001495 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001497 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001498}
1499
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001500static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001502 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001503}
1504
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001505static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001506 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001507 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001508 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001509 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001510 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1511 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001512}
1513
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001514static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001515 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1516 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001517 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001518 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1519 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001520 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001521 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001522 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001523 MotionEventBuilder motionBuilder =
1524 MotionEventBuilder(action, source)
1525 .displayId(displayId)
1526 .eventTime(eventTime)
1527 .rawXCursorPosition(cursorPosition.x)
1528 .rawYCursorPosition(cursorPosition.y)
1529 .pointer(
1530 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1531 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1532 motionBuilder.downTime(eventTime);
1533 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001534
1535 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001536 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1537 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001538}
1539
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001540static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1541 int32_t displayId,
1542 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001543 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001544}
1545
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001546static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1547 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001548 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001549 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001550}
1551
Jackal Guof9696682018-10-05 12:23:23 +08001552static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1553 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1554 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001555 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001556 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1557 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001558
1559 return args;
1560}
1561
Josep del Riob3981622023-04-18 15:49:45 +00001562static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1563 int32_t displayId = ADISPLAY_ID_NONE) {
1564 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1565 // Define a valid key event.
1566 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001567 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001568 currentTime);
1569
1570 return args;
1571}
1572
1573static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1574 int32_t displayId = ADISPLAY_ID_NONE) {
1575 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1576 // Define a valid key event.
1577 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001578 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001579 AMETA_NONE, currentTime);
1580
1581 return args;
1582}
1583
Prabir Pradhan678438e2023-04-13 19:32:51 +00001584[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1585 int32_t displayId,
1586 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001587 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001588 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1589 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1590 }
1591
chaviwd1c23182019-12-20 18:44:56 -08001592 PointerProperties pointerProperties[pointerCount];
1593 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001594
chaviwd1c23182019-12-20 18:44:56 -08001595 for (size_t i = 0; i < pointerCount; i++) {
1596 pointerProperties[i].clear();
1597 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001598 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001599
chaviwd1c23182019-12-20 18:44:56 -08001600 pointerCoords[i].clear();
1601 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1602 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1603 }
Jackal Guof9696682018-10-05 12:23:23 +08001604
1605 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1606 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001607 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001608 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1609 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001610 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001611 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001612 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001613 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001614
1615 return args;
1616}
1617
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001618static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1619 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1620}
1621
chaviwd1c23182019-12-20 18:44:56 -08001622static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1623 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1624}
1625
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001626static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1627 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001628 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001629}
1630
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001631} // namespace
1632
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001633/**
1634 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1635 * broken channel.
1636 */
1637TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1639 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001640 sp<FakeWindowHandle>::make(application, mDispatcher,
1641 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001642
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001643 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001644
1645 // Window closes its channel, but the window remains.
1646 window->destroyReceiver();
1647 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1648}
1649
Arthur Hungb92218b2018-08-14 12:00:21 +08001650TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001652 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1653 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001654
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001655 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001657 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001659
1660 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001661 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001662}
1663
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001664TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001666 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1667 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001668
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001669 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001670 // Inject a MotionEvent to an unknown display.
1671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001672 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1674
1675 // Window should receive motion event.
1676 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1677}
1678
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001679/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001680 * Calling onWindowInfosChanged once should not cause any issues.
1681 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001682 * called twice.
1683 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001684TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1687 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001689
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001690 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001692 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695
1696 // Window should receive motion event.
1697 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1698}
1699
1700/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001701 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001702 */
1703TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1706 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001712 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001714 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715
1716 // Window should receive motion event.
1717 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1718}
1719
Arthur Hungb92218b2018-08-14 12:00:21 +08001720// The foreground window should receive the first touch down event.
1721TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001723 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001724 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001725 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001726 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001728 mDispatcher->onWindowInfosChanged(
1729 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001733
1734 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001735 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001736 windowSecond->assertNoEvents();
1737}
1738
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001739/**
1740 * Two windows: A top window, and a wallpaper behind the window.
1741 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1742 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001743 * 1. foregroundWindow <-- dup touch to wallpaper
1744 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001745 */
1746TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1748 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001750 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001751 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001752 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001753 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001755 mDispatcher->onWindowInfosChanged(
1756 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001759 {100, 200}))
1760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1761
1762 // Both foreground window and its wallpaper should receive the touch down
1763 foregroundWindow->consumeMotionDown();
1764 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1765
1766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001767 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001768 ADISPLAY_ID_DEFAULT, {110, 200}))
1769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1770
1771 foregroundWindow->consumeMotionMove();
1772 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1773
1774 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001775 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776 foregroundWindow->consumeMotionCancel();
1777 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1778 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1779}
1780
1781/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001782 * Two fingers down on the window, and lift off the first finger.
1783 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1784 * contains a single pointer.
1785 */
1786TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1788 sp<FakeWindowHandle> window =
1789 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1790
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001792 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1794 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1795 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001796 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001797 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1798 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1799 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1800 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001801 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001802 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1803 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1804 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1805 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001806 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1807 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1808 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1809
1810 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001811 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001812 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1813 window->consumeMotionEvent(
1814 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1815}
1816
1817/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001818 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1819 * with the following differences:
1820 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1821 * clean up the connection.
1822 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1823 * Ensure that there's no crash in the dispatcher.
1824 */
1825TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1826 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1827 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001828 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001829 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001830 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001831 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001832 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001833
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001834 mDispatcher->onWindowInfosChanged(
1835 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001838 {100, 200}))
1839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1840
1841 // Both foreground window and its wallpaper should receive the touch down
1842 foregroundWindow->consumeMotionDown();
1843 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1844
1845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001846 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001847 ADISPLAY_ID_DEFAULT, {110, 200}))
1848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1849
1850 foregroundWindow->consumeMotionMove();
1851 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1852
1853 // Wallpaper closes its channel, but the window remains.
1854 wallpaperWindow->destroyReceiver();
1855 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1856
1857 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1858 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001859 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001860 foregroundWindow->consumeMotionCancel();
1861}
1862
Arthur Hungc539dbb2022-12-08 07:45:36 +00001863class ShouldSplitTouchFixture : public InputDispatcherTest,
1864 public ::testing::WithParamInterface<bool> {};
1865INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1866 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001867/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001868 * A single window that receives touch (on top), and a wallpaper window underneath it.
1869 * The top window gets a multitouch gesture.
1870 * Ensure that wallpaper gets the same gesture.
1871 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001872TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001874 sp<FakeWindowHandle> foregroundWindow =
1875 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1876 foregroundWindow->setDupTouchToWallpaper(true);
1877 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001878
1879 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001880 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001881 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001883 mDispatcher->onWindowInfosChanged(
1884 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885
1886 // Touch down on top window
1887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001888 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001889 {100, 100}))
1890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1891
1892 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001893 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001894 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1895
1896 // Second finger down on the top window
1897 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001898 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001899 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001900 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1901 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 .build();
1903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001904 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905 InputEventInjectionSync::WAIT_FOR_RESULT))
1906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1907
Harry Cutts33476232023-01-30 19:57:29 +00001908 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1909 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001910 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001911
1912 const MotionEvent secondFingerUpEvent =
1913 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1914 .displayId(ADISPLAY_ID_DEFAULT)
1915 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001916 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1917 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001918 .build();
1919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001920 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001921 InputEventInjectionSync::WAIT_FOR_RESULT))
1922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1923 foregroundWindow->consumeMotionPointerUp(0);
1924 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1925
1926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001927 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001928 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1929 AINPUT_SOURCE_TOUCHSCREEN)
1930 .displayId(ADISPLAY_ID_DEFAULT)
1931 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001933 .x(100)
1934 .y(100))
1935 .build(),
1936 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1938 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1939 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001940}
1941
1942/**
1943 * Two windows: a window on the left and window on the right.
1944 * A third window, wallpaper, is behind both windows, and spans both top windows.
1945 * The first touch down goes to the left window. A second pointer touches down on the right window.
1946 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1947 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1948 * ACTION_POINTER_DOWN(1).
1949 */
1950TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1952 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001953 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001954 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001955 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956
1957 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001958 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001959 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001960 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001961
1962 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001963 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001965 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001966
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001967 mDispatcher->onWindowInfosChanged(
1968 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1969 {},
1970 0,
1971 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972
1973 // Touch down on left window
1974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976 {100, 100}))
1977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1978
1979 // Both foreground window and its wallpaper should receive the touch down
1980 leftWindow->consumeMotionDown();
1981 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1982
1983 // Second finger down on the right window
1984 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001985 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001986 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001987 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1988 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989 .build();
1990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001991 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001992 InputEventInjectionSync::WAIT_FOR_RESULT))
1993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1994
1995 leftWindow->consumeMotionMove();
1996 // Since the touch is split, right window gets ACTION_DOWN
1997 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001998 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 expectedWallpaperFlags);
2000
2001 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002002 mDispatcher->onWindowInfosChanged(
2003 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 leftWindow->consumeMotionCancel();
2005 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2006 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2007
2008 // The pointer that's still down on the right window moves, and goes to the right window only.
2009 // As far as the dispatcher's concerned though, both pointers are still present.
2010 const MotionEvent secondFingerMoveEvent =
2011 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2012 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002013 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2014 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 .build();
2016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002017 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002018 InputEventInjectionSync::WAIT_FOR_RESULT));
2019 rightWindow->consumeMotionMove();
2020
2021 leftWindow->assertNoEvents();
2022 rightWindow->assertNoEvents();
2023 wallpaperWindow->assertNoEvents();
2024}
2025
Arthur Hungc539dbb2022-12-08 07:45:36 +00002026/**
2027 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2028 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2029 * The right window should receive ACTION_DOWN.
2030 */
2031TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002033 sp<FakeWindowHandle> leftWindow =
2034 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2035 leftWindow->setFrame(Rect(0, 0, 200, 200));
2036 leftWindow->setDupTouchToWallpaper(true);
2037 leftWindow->setSlippery(true);
2038
2039 sp<FakeWindowHandle> rightWindow =
2040 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2041 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002042
2043 sp<FakeWindowHandle> wallpaperWindow =
2044 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2045 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002046
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002047 mDispatcher->onWindowInfosChanged(
2048 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2049 {},
2050 0,
2051 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002052
Arthur Hungc539dbb2022-12-08 07:45:36 +00002053 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002058
2059 // Both foreground window and its wallpaper should receive the touch down
2060 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002061 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2062
Arthur Hungc539dbb2022-12-08 07:45:36 +00002063 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002065 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002066 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2068
Arthur Hungc539dbb2022-12-08 07:45:36 +00002069 leftWindow->consumeMotionCancel();
2070 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2071 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002072}
2073
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002074/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002075 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2076 * interactive, it might stop sending this flag.
2077 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2078 * to have a consistent input stream.
2079 *
2080 * Test procedure:
2081 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2082 * DOWN (new gesture).
2083 *
2084 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2085 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2086 *
2087 * We technically just need a single window here, but we are using two windows (spy on top and a
2088 * regular window below) to emulate the actual situation where it happens on the device.
2089 */
2090TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2092 sp<FakeWindowHandle> spyWindow =
2093 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2094 spyWindow->setFrame(Rect(0, 0, 200, 200));
2095 spyWindow->setTrustedOverlay(true);
2096 spyWindow->setSpy(true);
2097
2098 sp<FakeWindowHandle> window =
2099 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2100 window->setFrame(Rect(0, 0, 200, 200));
2101
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002102 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002103 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002104
2105 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002106 mDispatcher->notifyMotion(
2107 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2108 .deviceId(touchDeviceId)
2109 .policyFlags(DEFAULT_POLICY_FLAGS)
2110 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2111 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002112
Prabir Pradhan678438e2023-04-13 19:32:51 +00002113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2114 .deviceId(touchDeviceId)
2115 .policyFlags(DEFAULT_POLICY_FLAGS)
2116 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2117 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2118 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002119 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2120 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2121 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2122 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2123
2124 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002125 mDispatcher->notifyMotion(
2126 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2127 .deviceId(touchDeviceId)
2128 .policyFlags(0)
2129 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2130 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2131 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002132 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2133 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2134
2135 // We don't need to reset the device to reproduce the issue, but the reset event typically
2136 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002137 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002138
2139 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002140 mDispatcher->notifyMotion(
2141 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2142 .deviceId(touchDeviceId)
2143 .policyFlags(DEFAULT_POLICY_FLAGS)
2144 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2145 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002146 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2147 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2148
2149 // No more events
2150 spyWindow->assertNoEvents();
2151 window->assertNoEvents();
2152}
2153
2154/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002155 * Two windows: a window on the left and a window on the right.
2156 * Mouse is hovered from the right window into the left window.
2157 * Next, we tap on the left window, where the cursor was last seen.
2158 * The second tap is done onto the right window.
2159 * The mouse and tap are from two different devices.
2160 * We technically don't need to set the downtime / eventtime for these events, but setting these
2161 * explicitly helps during debugging.
2162 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2163 * In the buggy implementation, a tap on the right window would cause a crash.
2164 */
2165TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2167 sp<FakeWindowHandle> leftWindow =
2168 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2169 leftWindow->setFrame(Rect(0, 0, 200, 200));
2170
2171 sp<FakeWindowHandle> rightWindow =
2172 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2173 rightWindow->setFrame(Rect(200, 0, 400, 200));
2174
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002175 mDispatcher->onWindowInfosChanged(
2176 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002177 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2178 // stale.
2179 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2180 const int32_t mouseDeviceId = 6;
2181 const int32_t touchDeviceId = 4;
2182 // Move the cursor from right
2183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002184 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2186 AINPUT_SOURCE_MOUSE)
2187 .deviceId(mouseDeviceId)
2188 .downTime(baseTime + 10)
2189 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002190 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002191 .build()));
2192 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2193
2194 // .. to the left window
2195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002196 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002197 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2198 AINPUT_SOURCE_MOUSE)
2199 .deviceId(mouseDeviceId)
2200 .downTime(baseTime + 10)
2201 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002202 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002203 .build()));
2204 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2205 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2206 // Now tap the left window
2207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002208 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002209 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2210 AINPUT_SOURCE_TOUCHSCREEN)
2211 .deviceId(touchDeviceId)
2212 .downTime(baseTime + 40)
2213 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002214 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002215 .build()));
2216 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2217 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2218
2219 // release tap
2220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002221 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002222 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2223 AINPUT_SOURCE_TOUCHSCREEN)
2224 .deviceId(touchDeviceId)
2225 .downTime(baseTime + 40)
2226 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002227 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002228 .build()));
2229 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2230
2231 // Tap the window on the right
2232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002233 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002234 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2235 AINPUT_SOURCE_TOUCHSCREEN)
2236 .deviceId(touchDeviceId)
2237 .downTime(baseTime + 60)
2238 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002239 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 .build()));
2241 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2242
2243 // release tap
2244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002245 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002246 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2247 AINPUT_SOURCE_TOUCHSCREEN)
2248 .deviceId(touchDeviceId)
2249 .downTime(baseTime + 60)
2250 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002251 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002252 .build()));
2253 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2254
2255 // No more events
2256 leftWindow->assertNoEvents();
2257 rightWindow->assertNoEvents();
2258}
2259
2260/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002261 * Start hovering in a window. While this hover is still active, make another window appear on top.
2262 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2263 * While the top window is present, the hovering is stopped.
2264 * Later, hovering gets resumed again.
2265 * Ensure that new hover gesture is handled correctly.
2266 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2267 * to the window that's currently being hovered over.
2268 */
2269TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2271 sp<FakeWindowHandle> window =
2272 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2273 window->setFrame(Rect(0, 0, 200, 200));
2274
2275 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002276 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002277
2278 // Start hovering in the window
2279 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2280 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2281 .build());
2282 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2283
2284 // Now, an obscuring window appears!
2285 sp<FakeWindowHandle> obscuringWindow =
2286 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2287 ADISPLAY_ID_DEFAULT,
2288 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2289 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2290 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2291 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2292 obscuringWindow->setNoInputChannel(true);
2293 obscuringWindow->setFocusable(false);
2294 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002295 mDispatcher->onWindowInfosChanged(
2296 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002297
2298 // While this new obscuring window is present, the hovering is stopped
2299 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2300 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2301 .build());
2302 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2303
2304 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002306
2307 // And a new hover gesture starts.
2308 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2310 .build());
2311 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2312}
2313
2314/**
2315 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2316 * the obscuring window.
2317 */
2318TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2320 sp<FakeWindowHandle> window =
2321 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2322 window->setFrame(Rect(0, 0, 200, 200));
2323
2324 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002325 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002326
2327 // Start hovering in the window
2328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2329 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2330 .build());
2331 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2332
2333 // Now, an obscuring window appears!
2334 sp<FakeWindowHandle> obscuringWindow =
2335 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2336 ADISPLAY_ID_DEFAULT,
2337 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2338 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2339 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2340 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2341 obscuringWindow->setNoInputChannel(true);
2342 obscuringWindow->setFocusable(false);
2343 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002344 mDispatcher->onWindowInfosChanged(
2345 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002346
2347 // While this new obscuring window is present, the hovering continues. The event can't go to the
2348 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2349 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2350 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2351 .build());
2352 obscuringWindow->assertNoEvents();
2353 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2354
2355 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002357
2358 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2359 // so it should generate a HOVER_ENTER
2360 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2361 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2362 .build());
2363 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2364
2365 // Now the MOVE should be getting dispatched normally
2366 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2367 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2368 .build());
2369 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2370}
2371
2372/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002373 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2374 * events are delivered to the window.
2375 */
2376TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2377 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2378 sp<FakeWindowHandle> window =
2379 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2380 window->setFrame(Rect(0, 0, 200, 200));
2381 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2382
2383 // Start hovering in the window
2384 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2385 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2386 .build());
2387 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2388
2389 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2390 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2391 .build());
2392 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2393
2394 // Scroll with the mouse
2395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2396 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2397 .build());
2398 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2399}
2400
2401using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2402
2403/**
2404 * One window. Stylus down on the window. Next, touch from another device goes down.
2405 */
2406TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2407 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2408 sp<FakeWindowHandle> window =
2409 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2410 window->setFrame(Rect(0, 0, 200, 200));
2411
2412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2413
2414 constexpr int32_t touchDeviceId = 4;
2415 constexpr int32_t stylusDeviceId = 2;
2416
2417 // Stylus down
2418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2419 .deviceId(stylusDeviceId)
2420 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2421 .build());
2422 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2423
2424 // Touch down
2425 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2426 .deviceId(touchDeviceId)
2427 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2428 .build());
2429 // Touch cancels stylus
2430 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2431 WithCoords(100, 110)));
2432 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2433 WithCoords(140, 145)));
2434
2435 // Touch move
2436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2437 .deviceId(touchDeviceId)
2438 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2439 .build());
2440 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2441 WithCoords(141, 146)));
2442
2443 // Subsequent stylus movements are dropped
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2445 .deviceId(stylusDeviceId)
2446 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2447 .build());
2448 window->assertNoEvents();
2449}
2450
2451/**
2452 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2453 * down.
2454 * Similar test as above, but with added SPY window.
2455 */
2456TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2457 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2458 sp<FakeWindowHandle> window =
2459 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2460 sp<FakeWindowHandle> spyWindow =
2461 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2462 spyWindow->setFrame(Rect(0, 0, 200, 200));
2463 spyWindow->setTrustedOverlay(true);
2464 spyWindow->setSpy(true);
2465 window->setFrame(Rect(0, 0, 200, 200));
2466
2467 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2468
2469 constexpr int32_t touchDeviceId = 4;
2470 constexpr int32_t stylusDeviceId = 2;
2471
2472 // Stylus down
2473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2474 .deviceId(stylusDeviceId)
2475 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2476 .build());
2477 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2478 spyWindow->consumeMotionEvent(
2479 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2480
2481 // Touch down
2482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2483 .deviceId(touchDeviceId)
2484 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2485 .build());
2486
2487 // Touch move
2488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2491 .build());
2492 window->consumeMotionEvent(
2493 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2494 spyWindow->consumeMotionEvent(
2495 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2496 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2497 spyWindow->consumeMotionEvent(
2498 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2499 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2500 spyWindow->consumeMotionEvent(
2501 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2502 // Subsequent stylus movements are dropped
2503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2504 .deviceId(stylusDeviceId)
2505 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2506 .build());
2507
2508 window->assertNoEvents();
2509 spyWindow->assertNoEvents();
2510}
2511
2512/**
2513 * One window. Stylus hover on the window. Next, touch from another device goes down.
2514 */
2515TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2517 sp<FakeWindowHandle> window =
2518 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2519 window->setFrame(Rect(0, 0, 200, 200));
2520
2521 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2522
2523 constexpr int32_t touchDeviceId = 4;
2524 constexpr int32_t stylusDeviceId = 2;
2525
2526 // Stylus down on the window
2527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2528 .deviceId(stylusDeviceId)
2529 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2530 .build());
2531 window->consumeMotionEvent(
2532 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2533
2534 // Touch down on window
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2536 .deviceId(touchDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2538 .build());
2539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2540 .deviceId(touchDeviceId)
2541 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2542 .build());
2543 window->consumeMotionEvent(
2544 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2545 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2546 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2547 // Subsequent stylus movements are ignored
2548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2549 .deviceId(stylusDeviceId)
2550 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2551 .build());
2552 window->assertNoEvents();
2553}
2554
2555/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002556 * Two windows: a window on the left and a window on the right.
2557 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2558 * down. Then, on the left window, also place second touch pointer down.
2559 * This test tries to reproduce a crash.
2560 * In the buggy implementation, second pointer down on the left window would cause a crash.
2561 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002562TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2564 sp<FakeWindowHandle> leftWindow =
2565 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2566 leftWindow->setFrame(Rect(0, 0, 200, 200));
2567
2568 sp<FakeWindowHandle> rightWindow =
2569 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2570 rightWindow->setFrame(Rect(200, 0, 400, 200));
2571
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002572 mDispatcher->onWindowInfosChanged(
2573 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002574
2575 const int32_t touchDeviceId = 4;
2576 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002577
2578 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2580 .deviceId(mouseDeviceId)
2581 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2582 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002583 leftWindow->consumeMotionEvent(
2584 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2585
2586 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2588 .deviceId(mouseDeviceId)
2589 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2590 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2591 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002592
2593 leftWindow->consumeMotionEvent(
2594 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2595 leftWindow->consumeMotionEvent(
2596 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2597
Prabir Pradhan678438e2023-04-13 19:32:51 +00002598 mDispatcher->notifyMotion(
2599 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2600 .deviceId(mouseDeviceId)
2601 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2602 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2604 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002605 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2606
2607 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2609 .deviceId(touchDeviceId)
2610 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2611 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002612 leftWindow->consumeMotionEvent(
2613 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002614 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2615
2616 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002617 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2618 .deviceId(touchDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2620 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2621 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002622 leftWindow->consumeMotionEvent(
2623 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2624 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2625 // current implementation.
2626 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2627 rightWindow->consumeMotionEvent(
2628 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2629
2630 leftWindow->assertNoEvents();
2631 rightWindow->assertNoEvents();
2632}
2633
2634/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002635 * Two windows: a window on the left and a window on the right.
2636 * Mouse is hovered on the left window and stylus is hovered on the right window.
2637 */
2638TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2640 sp<FakeWindowHandle> leftWindow =
2641 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2642 leftWindow->setFrame(Rect(0, 0, 200, 200));
2643
2644 sp<FakeWindowHandle> rightWindow =
2645 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2646 rightWindow->setFrame(Rect(200, 0, 400, 200));
2647
2648 mDispatcher->onWindowInfosChanged(
2649 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2650
2651 const int32_t stylusDeviceId = 3;
2652 const int32_t mouseDeviceId = 6;
2653
2654 // Start hovering over the left window
2655 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2656 .deviceId(mouseDeviceId)
2657 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2658 .build());
2659 leftWindow->consumeMotionEvent(
2660 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2661
2662 // Stylus hovered on right window
2663 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2664 .deviceId(stylusDeviceId)
2665 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2666 .build());
2667 leftWindow->consumeMotionEvent(
2668 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2669 rightWindow->consumeMotionEvent(
2670 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2671
2672 // Subsequent HOVER_MOVE events are dispatched correctly.
2673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2674 .deviceId(mouseDeviceId)
2675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2676 .build());
2677 leftWindow->consumeMotionEvent(
2678 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2679 rightWindow->consumeMotionEvent(
2680 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2681
2682 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2683 .deviceId(stylusDeviceId)
2684 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2685 .build());
2686 leftWindow->consumeMotionEvent(
2687 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2688 rightWindow->consumeMotionEvent(
2689 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2690
2691 leftWindow->assertNoEvents();
2692 rightWindow->assertNoEvents();
2693}
2694
2695/**
2696 * Three windows: a window on the left and a window on the right.
2697 * And a spy window that's positioned above all of them.
2698 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2699 * Check the stream that's received by the spy.
2700 */
2701TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2703
2704 sp<FakeWindowHandle> spyWindow =
2705 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2706 spyWindow->setFrame(Rect(0, 0, 400, 400));
2707 spyWindow->setTrustedOverlay(true);
2708 spyWindow->setSpy(true);
2709
2710 sp<FakeWindowHandle> leftWindow =
2711 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2712 leftWindow->setFrame(Rect(0, 0, 200, 200));
2713
2714 sp<FakeWindowHandle> rightWindow =
2715 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2716
2717 rightWindow->setFrame(Rect(200, 0, 400, 200));
2718
2719 mDispatcher->onWindowInfosChanged(
2720 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2721
2722 const int32_t stylusDeviceId = 1;
2723 const int32_t touchDeviceId = 2;
2724
2725 // Stylus down on the left window
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2729 .build());
2730 leftWindow->consumeMotionEvent(
2731 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2732 spyWindow->consumeMotionEvent(
2733 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2734
2735 // Touch down on the right window
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2737 .deviceId(touchDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2739 .build());
2740 leftWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2742 spyWindow->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2744 rightWindow->consumeMotionEvent(
2745 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2746 spyWindow->consumeMotionEvent(
2747 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2748
2749 // Stylus movements continue, but are ignored because the touch went down more recently.
2750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2751 .deviceId(stylusDeviceId)
2752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2753 .build());
2754
2755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2756 .deviceId(touchDeviceId)
2757 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2758 .build());
2759 rightWindow->consumeMotionEvent(
2760 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2761 spyWindow->consumeMotionEvent(
2762 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2763
2764 spyWindow->assertNoEvents();
2765 leftWindow->assertNoEvents();
2766 rightWindow->assertNoEvents();
2767}
2768
2769/**
2770 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2771 * both.
2772 * Check hover in left window and touch down in the right window.
2773 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2774 */
2775TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2777
2778 sp<FakeWindowHandle> spyWindow =
2779 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2780 spyWindow->setFrame(Rect(0, 0, 400, 400));
2781 spyWindow->setTrustedOverlay(true);
2782 spyWindow->setSpy(true);
2783
2784 sp<FakeWindowHandle> leftWindow =
2785 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2786 leftWindow->setFrame(Rect(0, 0, 200, 200));
2787
2788 sp<FakeWindowHandle> rightWindow =
2789 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2790 rightWindow->setFrame(Rect(200, 0, 400, 200));
2791
2792 mDispatcher->onWindowInfosChanged(
2793 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2794
2795 const int32_t stylusDeviceId = 1;
2796 const int32_t touchDeviceId = 2;
2797
2798 // Stylus hover on the left window
2799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2800 .deviceId(stylusDeviceId)
2801 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2802 .build());
2803 leftWindow->consumeMotionEvent(
2804 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2805 spyWindow->consumeMotionEvent(
2806 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2807
2808 // Touch down on the right window.
2809 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2810 .deviceId(touchDeviceId)
2811 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2812 .build());
2813 leftWindow->consumeMotionEvent(
2814 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2815 spyWindow->consumeMotionEvent(
2816 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2817 spyWindow->consumeMotionEvent(
2818 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2819 rightWindow->consumeMotionEvent(
2820 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2821
2822 // Stylus movements continue, but are ignored because the touch is down.
2823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2824 .deviceId(stylusDeviceId)
2825 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2826 .build());
2827
2828 // Touch movements continue. They should be delivered to the right window and to the spy
2829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2830 .deviceId(touchDeviceId)
2831 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2832 .build());
2833 spyWindow->consumeMotionEvent(
2834 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2835 rightWindow->consumeMotionEvent(
2836 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2837
2838 spyWindow->assertNoEvents();
2839 leftWindow->assertNoEvents();
2840 rightWindow->assertNoEvents();
2841}
2842
2843/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002844 * On a single window, use two different devices: mouse and touch.
2845 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2846 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2847 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2848 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2849 * represent a new gesture.
2850 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002851TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2853 sp<FakeWindowHandle> window =
2854 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2855 window->setFrame(Rect(0, 0, 400, 400));
2856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002857 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858
2859 const int32_t touchDeviceId = 4;
2860 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002861
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002862 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2864 .deviceId(touchDeviceId)
2865 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2866 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002867 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002868 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2869 .deviceId(touchDeviceId)
2870 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2871 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2872 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002873 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002874 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2875 .deviceId(touchDeviceId)
2876 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2877 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002879 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2880 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2881 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2882
2883 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2885 .deviceId(mouseDeviceId)
2886 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2887 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2888 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002889
2890 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002891 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002892 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2893
Prabir Pradhan678438e2023-04-13 19:32:51 +00002894 mDispatcher->notifyMotion(
2895 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2896 .deviceId(mouseDeviceId)
2897 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2898 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2899 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2900 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002901 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2902
2903 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002904 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2905 .deviceId(touchDeviceId)
2906 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2907 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2908 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002909 // Since we already canceled this touch gesture, it will be ignored until a completely new
2910 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2911 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2912 // However, mouse movements should continue to work.
2913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2914 .deviceId(mouseDeviceId)
2915 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2916 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2917 .build());
2918 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2919
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002920 window->assertNoEvents();
2921}
2922
2923/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002924 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2925 * the injected event.
2926 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002927TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2929 sp<FakeWindowHandle> window =
2930 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2931 window->setFrame(Rect(0, 0, 400, 400));
2932
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002933 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002934
2935 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002936 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2937 // completion.
2938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002939 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002940 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2941 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002942 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002943 .build()));
2944 window->consumeMotionEvent(
2945 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2946
2947 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2948 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002949 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2950 .deviceId(touchDeviceId)
2951 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2952 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002953
2954 window->consumeMotionEvent(
2955 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2956 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2957}
2958
2959/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002960 * This test is similar to the test above, but the sequence of injected events is different.
2961 *
2962 * Two windows: a window on the left and a window on the right.
2963 * Mouse is hovered over the left window.
2964 * Next, we tap on the left window, where the cursor was last seen.
2965 *
2966 * After that, we inject one finger down onto the right window, and then a second finger down onto
2967 * the left window.
2968 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2969 * window (first), and then another on the left window (second).
2970 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2971 * In the buggy implementation, second finger down on the left window would cause a crash.
2972 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002973TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2975 sp<FakeWindowHandle> leftWindow =
2976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2977 leftWindow->setFrame(Rect(0, 0, 200, 200));
2978
2979 sp<FakeWindowHandle> rightWindow =
2980 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2981 rightWindow->setFrame(Rect(200, 0, 400, 200));
2982
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002983 mDispatcher->onWindowInfosChanged(
2984 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002985
2986 const int32_t mouseDeviceId = 6;
2987 const int32_t touchDeviceId = 4;
2988 // Hover over the left window. Keep the cursor there.
2989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002990 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002991 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2992 AINPUT_SOURCE_MOUSE)
2993 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002994 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002995 .build()));
2996 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2997
2998 // Tap on left window
2999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003000 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003001 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3002 AINPUT_SOURCE_TOUCHSCREEN)
3003 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003004 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003005 .build()));
3006
3007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003008 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003009 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3010 AINPUT_SOURCE_TOUCHSCREEN)
3011 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003012 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003013 .build()));
3014 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3015 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3016 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3017
3018 // First finger down on right window
3019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003020 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003021 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3022 AINPUT_SOURCE_TOUCHSCREEN)
3023 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003024 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003025 .build()));
3026 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3027
3028 // Second finger down on the left window
3029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003030 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003031 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3032 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003033 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3034 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003035 .build()));
3036 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3037 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3038
3039 // No more events
3040 leftWindow->assertNoEvents();
3041 rightWindow->assertNoEvents();
3042}
3043
3044/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003045 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3046 * While the touch is down, new hover events from the stylus device should be ignored. After the
3047 * touch is gone, stylus hovering should start working again.
3048 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003049TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3051 sp<FakeWindowHandle> window =
3052 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3053 window->setFrame(Rect(0, 0, 200, 200));
3054
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003055 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003056
3057 const int32_t stylusDeviceId = 5;
3058 const int32_t touchDeviceId = 4;
3059 // Start hovering with stylus
3060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003061 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003062 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003063 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003064 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003065 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003066 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003067
3068 // Finger down on the window
3069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003070 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003071 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003072 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003073 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003074 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003075 window->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3077 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003078
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003079 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003080 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003081 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003082 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3083 AINPUT_SOURCE_STYLUS)
3084 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003085 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003086 .build()));
3087 // No event should be sent. This event should be ignored because a pointer from another device
3088 // is already down.
3089
3090 // Lift up the finger
3091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003092 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003093 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3094 AINPUT_SOURCE_TOUCHSCREEN)
3095 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003096 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003097 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003098 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003099
3100 // Now that the touch is gone, stylus hovering should start working again
3101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003102 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003103 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3104 AINPUT_SOURCE_STYLUS)
3105 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003106 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003107 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003108 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3109 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003110 window->assertNoEvents();
3111}
3112
3113/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114 * A spy window above a window with no input channel.
3115 * Start hovering with a stylus device, and then tap with it.
3116 * Ensure spy window receives the entire sequence.
3117 */
3118TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3120 sp<FakeWindowHandle> spyWindow =
3121 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3122 spyWindow->setFrame(Rect(0, 0, 200, 200));
3123 spyWindow->setTrustedOverlay(true);
3124 spyWindow->setSpy(true);
3125 sp<FakeWindowHandle> window =
3126 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3127 window->setNoInputChannel(true);
3128 window->setFrame(Rect(0, 0, 200, 200));
3129
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003130 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003131
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003132 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3134 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3137 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003138 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3139 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3140 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003141 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3142
3143 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3145 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3146 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003147 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3148
3149 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003150 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3151 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3152 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003153 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3154
3155 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003156 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3157 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3158 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003159 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3160 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3162 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3163 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003164 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3165
3166 // No more events
3167 spyWindow->assertNoEvents();
3168 window->assertNoEvents();
3169}
3170
3171/**
3172 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3173 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3174 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3175 * While the mouse is down, new move events from the touch device should be ignored.
3176 */
3177TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3179 sp<FakeWindowHandle> spyWindow =
3180 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3181 spyWindow->setFrame(Rect(0, 0, 200, 200));
3182 spyWindow->setTrustedOverlay(true);
3183 spyWindow->setSpy(true);
3184 sp<FakeWindowHandle> window =
3185 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3186 window->setFrame(Rect(0, 0, 200, 200));
3187
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003188 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003189
3190 const int32_t mouseDeviceId = 7;
3191 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003192
3193 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003194 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3195 .deviceId(mouseDeviceId)
3196 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3197 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003198 spyWindow->consumeMotionEvent(
3199 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3200 window->consumeMotionEvent(
3201 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3202
3203 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003204 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3205 .deviceId(touchDeviceId)
3206 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3207 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003208 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3209 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3210 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3211 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3212
Prabir Pradhan678438e2023-04-13 19:32:51 +00003213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3214 .deviceId(touchDeviceId)
3215 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3216 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003217 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3218 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3219
3220 // Pilfer the stream
3221 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3222 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3223
Prabir Pradhan678438e2023-04-13 19:32:51 +00003224 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3225 .deviceId(touchDeviceId)
3226 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3227 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003228 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3229
3230 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003231 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
3233 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3234 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3235 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003236
3237 spyWindow->consumeMotionEvent(
3238 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3239 spyWindow->consumeMotionEvent(
3240 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3241 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3242
Prabir Pradhan678438e2023-04-13 19:32:51 +00003243 mDispatcher->notifyMotion(
3244 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3245 .deviceId(mouseDeviceId)
3246 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3247 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3248 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3249 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003250 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3251 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3252
3253 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003254 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3255 .deviceId(mouseDeviceId)
3256 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3257 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3258 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003259 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3260 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3261
3262 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3264 .deviceId(touchDeviceId)
3265 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3266 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003267
3268 // No more events
3269 spyWindow->assertNoEvents();
3270 window->assertNoEvents();
3271}
3272
3273/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003274 * On the display, have a single window, and also an area where there's no window.
3275 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3276 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3277 */
3278TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3280 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003281 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003282
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003283 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003284
3285 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003286 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003287
3288 mDispatcher->waitForIdle();
3289 window->assertNoEvents();
3290
3291 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003292 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003293 mDispatcher->waitForIdle();
3294 window->consumeMotionDown();
3295}
3296
3297/**
3298 * Same test as above, but instead of touching the empty space, the first touch goes to
3299 * non-touchable window.
3300 */
3301TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3302 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3303 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003304 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003305 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3306 window1->setTouchable(false);
3307 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003308 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003309 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3310
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003311 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003312
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003313 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003314 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003315
3316 mDispatcher->waitForIdle();
3317 window1->assertNoEvents();
3318 window2->assertNoEvents();
3319
3320 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003321 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003322 mDispatcher->waitForIdle();
3323 window2->consumeMotionDown();
3324}
3325
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003326/**
3327 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3328 * to the event time of the first ACTION_DOWN sent to the particular window.
3329 */
3330TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3332 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003333 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003334 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3335 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003336 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003337 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3338
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003339 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003340
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003341 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003342 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003343
3344 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345
3346 MotionEvent* motionEvent1 = window1->consumeMotion();
3347 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003348 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003349 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3350 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003351
3352 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003353 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003354 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 MotionEvent* motionEvent2 = window2->consumeMotion();
3356 ASSERT_NE(motionEvent2, nullptr);
3357 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003358 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003359 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003360
3361 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003362 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003363 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003364 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003365
3366 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003367 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003368 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003369 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003370
3371 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3372 window1->consumeMotionMove();
3373 window1->assertNoEvents();
3374
3375 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003376 mDispatcher->notifyMotion(
3377 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003378 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003379 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003380
Prabir Pradhan678438e2023-04-13 19:32:51 +00003381 mDispatcher->notifyMotion(
3382 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003383 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003384 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003385}
3386
Garfield Tandf26e862020-07-01 20:18:19 -07003387TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003389 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003390 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003391 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003392 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003393 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003394 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003395
3396 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003398 mDispatcher->onWindowInfosChanged(
3399 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003400
3401 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003403 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003404 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3405 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003406 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003407 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003408 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003409
3410 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003412 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003413 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3414 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003415 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003416 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003417 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3418 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003419
3420 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003422 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003423 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3424 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003425 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003426 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003427 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3428 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003429
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003431 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003432 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3433 AINPUT_SOURCE_MOUSE)
3434 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3435 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003436 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003437 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003438 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003439
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003441 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003442 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3443 AINPUT_SOURCE_MOUSE)
3444 .buttonState(0)
3445 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003446 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003447 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003448 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003449
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003451 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003452 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3453 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003454 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003455 .build()));
3456 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3457
3458 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003460 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003461 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3462 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003463 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003464 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003465 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003466
3467 // No more events
3468 windowLeft->assertNoEvents();
3469 windowRight->assertNoEvents();
3470}
3471
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003472/**
3473 * Put two fingers down (and don't release them) and click the mouse button.
3474 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3475 * currently active gesture should be canceled, and the new one should proceed.
3476 */
3477TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3478 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3479 sp<FakeWindowHandle> window =
3480 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3481 window->setFrame(Rect(0, 0, 600, 800));
3482
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003483 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003484
3485 const int32_t touchDeviceId = 4;
3486 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003487
3488 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3490 .deviceId(touchDeviceId)
3491 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3492 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003493
Prabir Pradhan678438e2023-04-13 19:32:51 +00003494 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3495 .deviceId(touchDeviceId)
3496 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3497 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3498 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003499 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3500 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3501
3502 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3504 .deviceId(mouseDeviceId)
3505 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3506 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3507 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003508 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3509 WithPointerCount(2u)));
3510 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3511
Prabir Pradhan678438e2023-04-13 19:32:51 +00003512 mDispatcher->notifyMotion(
3513 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3514 .deviceId(mouseDeviceId)
3515 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3516 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3517 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3518 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003519 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3520
3521 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3522 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3524 .deviceId(touchDeviceId)
3525 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3526 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3527 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003528 window->assertNoEvents();
3529}
3530
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003531TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3533
3534 sp<FakeWindowHandle> spyWindow =
3535 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3536 spyWindow->setFrame(Rect(0, 0, 600, 800));
3537 spyWindow->setTrustedOverlay(true);
3538 spyWindow->setSpy(true);
3539 sp<FakeWindowHandle> window =
3540 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3541 window->setFrame(Rect(0, 0, 600, 800));
3542
3543 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003544 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003545
3546 // Send mouse cursor to the window
3547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003548 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003549 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3550 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003551 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003552 .build()));
3553
3554 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3555 WithSource(AINPUT_SOURCE_MOUSE)));
3556 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3557 WithSource(AINPUT_SOURCE_MOUSE)));
3558
3559 window->assertNoEvents();
3560 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003561}
3562
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003563TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3565
3566 sp<FakeWindowHandle> spyWindow =
3567 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3568 spyWindow->setFrame(Rect(0, 0, 600, 800));
3569 spyWindow->setTrustedOverlay(true);
3570 spyWindow->setSpy(true);
3571 sp<FakeWindowHandle> window =
3572 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3573 window->setFrame(Rect(0, 0, 600, 800));
3574
3575 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003576 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003577
3578 // Send mouse cursor to the window
3579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003580 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003581 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3582 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003583 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003584 .build()));
3585
3586 // Move mouse cursor
3587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003588 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003589 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3590 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003592 .build()));
3593
3594 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3595 WithSource(AINPUT_SOURCE_MOUSE)));
3596 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3597 WithSource(AINPUT_SOURCE_MOUSE)));
3598 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3599 WithSource(AINPUT_SOURCE_MOUSE)));
3600 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3601 WithSource(AINPUT_SOURCE_MOUSE)));
3602 // Touch down on the window
3603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003604 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003605 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3606 AINPUT_SOURCE_TOUCHSCREEN)
3607 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003608 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003609 .build()));
3610 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3611 WithSource(AINPUT_SOURCE_MOUSE)));
3612 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3613 WithSource(AINPUT_SOURCE_MOUSE)));
3614 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3615 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3616 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3617 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3618
3619 // pilfer the motion, retaining the gesture on the spy window.
3620 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3621 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3622 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3623
3624 // Touch UP on the window
3625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003626 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003627 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3628 AINPUT_SOURCE_TOUCHSCREEN)
3629 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003630 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003631 .build()));
3632 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3633 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3634
3635 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3636 // to send a new gesture. It should again go to both windows (spy and the window below), just
3637 // like the first gesture did, before pilfering. The window configuration has not changed.
3638
3639 // One more tap - DOWN
3640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003641 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003642 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3643 AINPUT_SOURCE_TOUCHSCREEN)
3644 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003645 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003646 .build()));
3647 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3648 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3649 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3650 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3651
3652 // Touch UP on the window
3653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003654 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003655 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3656 AINPUT_SOURCE_TOUCHSCREEN)
3657 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003658 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003659 .build()));
3660 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3661 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3662 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3663 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3664
3665 window->assertNoEvents();
3666 spyWindow->assertNoEvents();
3667}
3668
Garfield Tandf26e862020-07-01 20:18:19 -07003669// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3670// directly in this test.
3671TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003673 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003674 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003675 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003676
3677 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3678
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003679 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003680
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003682 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003683 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3684 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003685 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003686 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003687 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003688 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003690 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003691 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3692 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003693 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003694 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003695 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3696 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003697
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003699 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003700 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3701 AINPUT_SOURCE_MOUSE)
3702 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3703 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003704 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003705 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003706 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003707
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003709 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003710 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3711 AINPUT_SOURCE_MOUSE)
3712 .buttonState(0)
3713 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003714 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003715 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003716 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003717
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003719 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003720 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3721 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003722 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003723 .build()));
3724 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3725
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003726 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3727 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3728 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003729 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003730 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3731 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003732 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003733 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003734 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003735}
3736
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003737/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003738 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3739 * is generated.
3740 */
3741TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3742 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3743 sp<FakeWindowHandle> window =
3744 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3745 window->setFrame(Rect(0, 0, 1200, 800));
3746
3747 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3748
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003749 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003750
3751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003752 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003753 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3754 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003755 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003756 .build()));
3757 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3758
3759 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003760 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003761 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3762}
3763
3764/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003765 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3766 */
3767TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3769 sp<FakeWindowHandle> window =
3770 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3771 window->setFrame(Rect(0, 0, 1200, 800));
3772
3773 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3774
3775 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3776
3777 MotionEventBuilder hoverEnterBuilder =
3778 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3779 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3780 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3782 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3784 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3785 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3786 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3787}
3788
3789/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003790 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3791 */
3792TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3794 sp<FakeWindowHandle> window =
3795 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3796 window->setFrame(Rect(0, 0, 100, 100));
3797
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003799
3800 const int32_t mouseDeviceId = 7;
3801 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003802
3803 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003804 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3805 .deviceId(mouseDeviceId)
3806 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3807 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003808 window->consumeMotionEvent(
3809 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3810
3811 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3813 .deviceId(touchDeviceId)
3814 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3815 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003816
3817 window->consumeMotionEvent(
3818 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3819 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3820}
3821
3822/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003823 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003824 * The tap causes a HOVER_EXIT event to be generated because the current event
3825 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003826 */
3827TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3829 sp<FakeWindowHandle> window =
3830 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3831 window->setFrame(Rect(0, 0, 100, 100));
3832
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003833 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3835 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3836 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003837 ASSERT_NO_FATAL_FAILURE(
3838 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3839 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003840
3841 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3843 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3844 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003845 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003846 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3847 WithSource(AINPUT_SOURCE_MOUSE))));
3848
3849 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003850 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3851 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3852
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3854 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3855 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003856 ASSERT_NO_FATAL_FAILURE(
3857 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3858 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3859}
3860
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003861TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3863 sp<FakeWindowHandle> windowDefaultDisplay =
3864 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3865 ADISPLAY_ID_DEFAULT);
3866 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3867 sp<FakeWindowHandle> windowSecondDisplay =
3868 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3869 SECOND_DISPLAY_ID);
3870 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3871
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003872 mDispatcher->onWindowInfosChanged(
3873 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003874
3875 // Set cursor position in window in default display and check that hover enter and move
3876 // events are generated.
3877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003878 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003879 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3880 AINPUT_SOURCE_MOUSE)
3881 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003882 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003883 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003884 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003885
3886 // Remove all windows in secondary display and check that no event happens on window in
3887 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003888 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3889
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003890 windowDefaultDisplay->assertNoEvents();
3891
3892 // Move cursor position in window in default display and check that only hover move
3893 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003894 mDispatcher->onWindowInfosChanged(
3895 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003897 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003898 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3899 AINPUT_SOURCE_MOUSE)
3900 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003901 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003902 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003903 windowDefaultDisplay->consumeMotionEvent(
3904 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3905 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003906 windowDefaultDisplay->assertNoEvents();
3907}
3908
Garfield Tan00f511d2019-06-12 16:55:40 -07003909TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003910 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003911
3912 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003913 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003914 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003915 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003916 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003917 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003918
3919 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3920
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003921 mDispatcher->onWindowInfosChanged(
3922 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003923
3924 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3925 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003927 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003928 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003929 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003930 windowRight->assertNoEvents();
3931}
3932
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003933TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003935 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3936 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003937 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003938
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003939 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003940 setFocusedWindow(window);
3941
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003942 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003943
Prabir Pradhan678438e2023-04-13 19:32:51 +00003944 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003945
3946 // Window should receive key down event.
3947 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3948
3949 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3950 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003951 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003952 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003953 AKEY_EVENT_FLAG_CANCELED);
3954}
3955
3956TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003958 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3959 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003960
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003961 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003962
Prabir Pradhan678438e2023-04-13 19:32:51 +00003963 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3964 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003965
3966 // Window should receive motion down event.
3967 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3968
3969 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3970 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003971 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003972 window->consumeMotionEvent(
3973 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003974}
3975
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003976TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3977 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3978 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3979 "Fake Window", ADISPLAY_ID_DEFAULT);
3980
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003981 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003982
3983 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3984 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3985 .build());
3986
3987 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3988
3989 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3990 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3991 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3992
3993 // After the device has been reset, a new hovering stream can be sent to the window
3994 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3995 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3996 .build());
3997 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3998}
3999
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004000TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004002 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4003 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004004 window->setFocusable(true);
4005
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004006 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004007 setFocusedWindow(window);
4008
4009 window->consumeFocusEvent(true);
4010
Prabir Pradhan678438e2023-04-13 19:32:51 +00004011 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004012 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4013 const nsecs_t injectTime = keyArgs.eventTime;
4014 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004015 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004016 // The dispatching time should be always greater than or equal to intercept key timeout.
4017 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4018 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4019 std::chrono::nanoseconds(interceptKeyTimeout).count());
4020}
4021
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004022/**
4023 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4024 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004025TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004027 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4028 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004029 window->setFocusable(true);
4030
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004031 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004032 setFocusedWindow(window);
4033
4034 window->consumeFocusEvent(true);
4035
Prabir Pradhan678438e2023-04-13 19:32:51 +00004036 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004037 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004038
4039 // Set a value that's significantly larger than the default consumption timeout. If the
4040 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4041 mFakePolicy->setInterceptKeyTimeout(600ms);
4042 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4043 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004044 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4045}
4046
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004047/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004048 * Two windows. First is a regular window. Second does not overlap with the first, and has
4049 * WATCH_OUTSIDE_TOUCH.
4050 * Both windows are owned by the same UID.
4051 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4052 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4053 */
4054TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4055 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004056 sp<FakeWindowHandle> window =
4057 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004058 window->setFrame(Rect{0, 0, 100, 100});
4059
4060 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004061 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004062 ADISPLAY_ID_DEFAULT);
4063 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4064 outsideWindow->setWatchOutsideTouch(true);
4065 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004066 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004067
4068 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004069 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4070 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4071 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004072 window->consumeMotionDown();
4073 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4074 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4075 outsideWindow->consumeMotionEvent(
4076 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4077}
4078
4079/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004080 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4081 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4082 * ACTION_OUTSIDE event is sent per gesture.
4083 */
4084TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4085 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004087 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4088 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004089 window->setWatchOutsideTouch(true);
4090 window->setFrame(Rect{0, 0, 100, 100});
4091 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004092 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4093 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004094 secondWindow->setFrame(Rect{100, 100, 200, 200});
4095 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004096 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4097 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004098 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004099 mDispatcher->onWindowInfosChanged(
4100 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004101
4102 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004103 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4104 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4105 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004106 window->assertNoEvents();
4107 secondWindow->assertNoEvents();
4108
4109 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4110 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004111 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4112 ADISPLAY_ID_DEFAULT,
4113 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004114 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4115 window->consumeMotionEvent(
4116 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004117 secondWindow->consumeMotionDown();
4118 thirdWindow->assertNoEvents();
4119
4120 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4121 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004122 mDispatcher->notifyMotion(
4123 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4124 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004125 window->assertNoEvents();
4126 secondWindow->consumeMotionMove();
4127 thirdWindow->consumeMotionDown();
4128}
4129
Prabir Pradhan814fe082022-07-22 20:22:18 +00004130TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4131 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004132 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4133 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004134 window->setFocusable(true);
4135
Patrick Williamsd828f302023-04-28 17:52:08 -05004136 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004137 setFocusedWindow(window);
4138
4139 window->consumeFocusEvent(true);
4140
Prabir Pradhan678438e2023-04-13 19:32:51 +00004141 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4142 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4143 mDispatcher->notifyKey(keyDown);
4144 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004145
4146 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4147 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4148
4149 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004150 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004151
4152 window->consumeFocusEvent(false);
4153
Prabir Pradhan678438e2023-04-13 19:32:51 +00004154 mDispatcher->notifyKey(keyDown);
4155 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004156 window->assertNoEvents();
4157}
4158
Arthur Hung96483742022-11-15 03:30:48 +00004159TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4161 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4162 "Fake Window", ADISPLAY_ID_DEFAULT);
4163 // Ensure window is non-split and have some transform.
4164 window->setPreventSplitting(true);
4165 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004166 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004167
4168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004169 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004170 {50, 50}))
4171 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4172 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4173
4174 const MotionEvent secondFingerDownEvent =
4175 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4176 .displayId(ADISPLAY_ID_DEFAULT)
4177 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004178 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4179 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004180 .build();
4181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004182 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004183 InputEventInjectionSync::WAIT_FOR_RESULT))
4184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4185
4186 const MotionEvent* event = window->consumeMotion();
4187 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4188 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4189 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4190 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4191 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4192}
4193
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004194/**
4195 * Two windows: a splittable and a non-splittable.
4196 * The non-splittable window shouldn't receive any "incomplete" gestures.
4197 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4198 * The second pointer should be dropped because the initial window is splittable, so it won't get
4199 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4200 * "incomplete" gestures.
4201 */
4202TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4204 sp<FakeWindowHandle> leftWindow =
4205 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4206 ADISPLAY_ID_DEFAULT);
4207 leftWindow->setPreventSplitting(false);
4208 leftWindow->setFrame(Rect(0, 0, 100, 100));
4209 sp<FakeWindowHandle> rightWindow =
4210 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4211 ADISPLAY_ID_DEFAULT);
4212 rightWindow->setPreventSplitting(true);
4213 rightWindow->setFrame(Rect(100, 100, 200, 200));
4214 mDispatcher->onWindowInfosChanged(
4215 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4216
4217 // Touch down on left, splittable window
4218 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4219 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4220 .build());
4221 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4222
4223 mDispatcher->notifyMotion(
4224 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4225 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4226 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4227 .build());
4228 leftWindow->assertNoEvents();
4229 rightWindow->assertNoEvents();
4230}
4231
Harry Cuttsb166c002023-05-09 13:06:05 +00004232TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4234 sp<FakeWindowHandle> window =
4235 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4236 window->setFrame(Rect(0, 0, 400, 400));
4237 sp<FakeWindowHandle> trustedOverlay =
4238 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4239 ADISPLAY_ID_DEFAULT);
4240 trustedOverlay->setSpy(true);
4241 trustedOverlay->setTrustedOverlay(true);
4242
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004243 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004244
4245 // Start a three-finger touchpad swipe
4246 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4247 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4248 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4249 .build());
4250 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4251 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4252 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4253 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4254 .build());
4255 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4256 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4257 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4258 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4259 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4260 .build());
4261
4262 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4263 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4264 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4265
4266 // Move the swipe a bit
4267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4268 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4269 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4270 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4271 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4272 .build());
4273
4274 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4275
4276 // End the swipe
4277 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4278 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4279 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4280 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4281 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4282 .build());
4283 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4284 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4285 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4286 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4287 .build());
4288 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4289 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4290 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4291 .build());
4292
4293 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4294 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4295 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4296
4297 window->assertNoEvents();
4298}
4299
4300TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4302 sp<FakeWindowHandle> window =
4303 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4304 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004306
4307 // Start a three-finger touchpad swipe
4308 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4309 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4310 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4311 .build());
4312 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4313 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4314 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4315 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4316 .build());
4317 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4318 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4319 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4320 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4321 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4322 .build());
4323
4324 // Move the swipe a bit
4325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4326 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4327 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4328 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4329 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4330 .build());
4331
4332 // End the swipe
4333 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4334 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4335 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4336 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4337 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4338 .build());
4339 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4340 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4341 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4342 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4343 .build());
4344 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4345 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4346 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4347 .build());
4348
4349 window->assertNoEvents();
4350}
4351
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004352/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004353 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4354 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004355 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004356 */
4357TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4359 sp<FakeWindowHandle> window =
4360 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4361 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004362 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004363
4364 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4366 .downTime(baseTime + 10)
4367 .eventTime(baseTime + 10)
4368 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4369 .build());
4370
4371 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4372
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004373 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004374 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004375
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004376 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004377
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004378 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4379 .downTime(baseTime + 10)
4380 .eventTime(baseTime + 30)
4381 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4382 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4383 .build());
4384
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004385 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4386
4387 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004388 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4389 .downTime(baseTime + 10)
4390 .eventTime(baseTime + 40)
4391 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4392 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4393 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004394
4395 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4396
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4398 .downTime(baseTime + 10)
4399 .eventTime(baseTime + 50)
4400 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4401 .build());
4402
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004403 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4404
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4406 .downTime(baseTime + 60)
4407 .eventTime(baseTime + 60)
4408 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4409 .build());
4410
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004411 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004412}
4413
4414/**
Hu Guo771a7692023-09-17 20:51:08 +08004415 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4416 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4417 * its coordinates should be converted by the transform of the windows of target screen.
4418 */
4419TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4420 // This case will create a window and a spy window on the default display and mirror
4421 // window on the second display. cancel event is sent through spy window pilferPointers
4422 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4423
4424 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4425 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4426 spyWindowDefaultDisplay->setTrustedOverlay(true);
4427 spyWindowDefaultDisplay->setSpy(true);
4428
4429 sp<FakeWindowHandle> windowDefaultDisplay =
4430 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4431 ADISPLAY_ID_DEFAULT);
4432 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4433
4434 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4435 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4436
4437 // Add the windows to the dispatcher
4438 mDispatcher->onWindowInfosChanged(
4439 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4440 *windowSecondDisplay->getInfo()},
4441 {},
4442 0,
4443 0});
4444
4445 // Send down to ADISPLAY_ID_DEFAULT
4446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4447 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4448 {100, 100}))
4449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4450
4451 spyWindowDefaultDisplay->consumeMotionDown();
4452 windowDefaultDisplay->consumeMotionDown();
4453
4454 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4455
4456 // windowDefaultDisplay gets cancel
4457 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4458 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4459
4460 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4461 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4462 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4463 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4464 EXPECT_EQ(100, event->getX(0));
4465 EXPECT_EQ(100, event->getY(0));
4466}
4467
4468/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004469 * Ensure the correct coordinate spaces are used by InputDispatcher.
4470 *
4471 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4472 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4473 * space.
4474 */
4475class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4476public:
4477 void SetUp() override {
4478 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004479 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004480 }
4481
4482 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4483 gui::DisplayInfo info;
4484 info.displayId = displayId;
4485 info.transform = transform;
4486 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004487 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004488 }
4489
4490 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4491 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004492 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004493 }
4494
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004495 void removeAllWindowsAndDisplays() {
4496 mDisplayInfos.clear();
4497 mWindowInfos.clear();
4498 }
4499
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004500 // Set up a test scenario where the display has a scaled projection and there are two windows
4501 // on the display.
4502 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4503 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4504 // respectively.
4505 ui::Transform displayTransform;
4506 displayTransform.set(2, 0, 0, 4);
4507 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4508
4509 std::shared_ptr<FakeApplicationHandle> application =
4510 std::make_shared<FakeApplicationHandle>();
4511
4512 // Add two windows to the display. Their frames are represented in the display space.
4513 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004514 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4515 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004516 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4517 addWindow(firstWindow);
4518
4519 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004520 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4521 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004522 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4523 addWindow(secondWindow);
4524 return {std::move(firstWindow), std::move(secondWindow)};
4525 }
4526
4527private:
4528 std::vector<gui::DisplayInfo> mDisplayInfos;
4529 std::vector<gui::WindowInfo> mWindowInfos;
4530};
4531
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004532TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004533 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4534 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004535 // selected so that if the hit test was performed with the point and the bounds being in
4536 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4538 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4539 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004540
4541 firstWindow->consumeMotionDown();
4542 secondWindow->assertNoEvents();
4543}
4544
4545// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4546// the event should be treated as being in the logical display space.
4547TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4548 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4549 // Send down to the first window. The point is represented in the logical display space. The
4550 // point is selected so that if the hit test was done in logical display space, then it would
4551 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004552 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004553 PointF{75 * 2, 55 * 4});
4554
4555 firstWindow->consumeMotionDown();
4556 secondWindow->assertNoEvents();
4557}
4558
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004559// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4560// event should be treated as being in the logical display space.
4561TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4562 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4563
4564 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4565 ui::Transform injectedEventTransform;
4566 injectedEventTransform.set(matrix);
4567 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4568 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4569
4570 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4571 .displayId(ADISPLAY_ID_DEFAULT)
4572 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004573 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004574 .x(untransformedPoint.x)
4575 .y(untransformedPoint.y))
4576 .build();
4577 event.transform(matrix);
4578
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004579 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004580 InputEventInjectionSync::WAIT_FOR_RESULT);
4581
4582 firstWindow->consumeMotionDown();
4583 secondWindow->assertNoEvents();
4584}
4585
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004586TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4587 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4588
4589 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004590 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4591 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4592 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004593
4594 firstWindow->assertNoEvents();
4595 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004596 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004597 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4598
4599 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4600 EXPECT_EQ(300, event->getRawX(0));
4601 EXPECT_EQ(880, event->getRawY(0));
4602
4603 // Ensure that the x and y values are in the window's coordinate space.
4604 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4605 // the logical display space. This will be the origin of the window space.
4606 EXPECT_EQ(100, event->getX(0));
4607 EXPECT_EQ(80, event->getY(0));
4608}
4609
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004610/** Ensure consistent behavior of InputDispatcher in all orientations. */
4611class InputDispatcherDisplayOrientationFixture
4612 : public InputDispatcherDisplayProjectionTest,
4613 public ::testing::WithParamInterface<ui::Rotation> {};
4614
4615// This test verifies the touchable region of a window for all rotations of the display by tapping
4616// in different locations on the display, specifically points close to the four corners of a
4617// window.
4618TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4619 constexpr static int32_t displayWidth = 400;
4620 constexpr static int32_t displayHeight = 800;
4621
4622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4623
4624 const auto rotation = GetParam();
4625
4626 // Set up the display with the specified rotation.
4627 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4628 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4629 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4630 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4631 logicalDisplayWidth, logicalDisplayHeight);
4632 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4633
4634 // Create a window with its bounds determined in the logical display.
4635 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4636 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4637 sp<FakeWindowHandle> window =
4638 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4639 window->setFrame(frameInDisplay, displayTransform);
4640 addWindow(window);
4641
4642 // The following points in logical display space should be inside the window.
4643 static const std::array<vec2, 4> insidePoints{
4644 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4645 for (const auto pointInsideWindow : insidePoints) {
4646 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4647 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004648 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4649 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4650 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004651 window->consumeMotionDown();
4652
Prabir Pradhan678438e2023-04-13 19:32:51 +00004653 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4654 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4655 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004656 window->consumeMotionUp();
4657 }
4658
4659 // The following points in logical display space should be outside the window.
4660 static const std::array<vec2, 5> outsidePoints{
4661 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4662 for (const auto pointOutsideWindow : outsidePoints) {
4663 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4664 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004665 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4666 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4667 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004668
Prabir Pradhan678438e2023-04-13 19:32:51 +00004669 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4670 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4671 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004672 }
4673 window->assertNoEvents();
4674}
4675
4676// Run the precision tests for all rotations.
4677INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4678 InputDispatcherDisplayOrientationFixture,
4679 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4680 ui::ROTATION_270),
4681 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4682 return ftl::enum_string(testParamInfo.param);
4683 });
4684
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004685using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4686 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004687
4688class TransferTouchFixture : public InputDispatcherTest,
4689 public ::testing::WithParamInterface<TransferFunction> {};
4690
4691TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004693
4694 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004695 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004696 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4697 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004698 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004699 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004700 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4701 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004702 sp<FakeWindowHandle> wallpaper =
4703 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4704 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004705 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004706 mDispatcher->onWindowInfosChanged(
4707 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004708
4709 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004710 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4711 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004712
Svet Ganov5d3bc372020-01-26 23:11:07 -08004713 // Only the first window should get the down event
4714 firstWindow->consumeMotionDown();
4715 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004716 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004717
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004718 // Transfer touch to the second window
4719 TransferFunction f = GetParam();
4720 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4721 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004722 // The first window gets cancel and the second gets down
4723 firstWindow->consumeMotionCancel();
4724 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004725 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004726
4727 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004728 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4729 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004730 // The first window gets no events and the second gets up
4731 firstWindow->assertNoEvents();
4732 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004733 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004734}
4735
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004736/**
4737 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4738 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4739 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4740 * natural to the user.
4741 * In this test, we are sending a pointer to both spy window and first window. We then try to
4742 * transfer touch to the second window. The dispatcher should identify the first window as the
4743 * one that should lose the gesture, and therefore the action should be to move the gesture from
4744 * the first window to the second.
4745 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4746 * the other API, as well.
4747 */
4748TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4750
4751 // Create a couple of windows + a spy window
4752 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004753 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004754 spyWindow->setTrustedOverlay(true);
4755 spyWindow->setSpy(true);
4756 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004757 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004758 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004759 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004760
4761 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004762 mDispatcher->onWindowInfosChanged(
4763 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004764
4765 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004766 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4767 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004768 // Only the first window and spy should get the down event
4769 spyWindow->consumeMotionDown();
4770 firstWindow->consumeMotionDown();
4771
4772 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4773 // if f === 'transferTouch'.
4774 TransferFunction f = GetParam();
4775 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4776 ASSERT_TRUE(success);
4777 // The first window gets cancel and the second gets down
4778 firstWindow->consumeMotionCancel();
4779 secondWindow->consumeMotionDown();
4780
4781 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004782 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4783 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004784 // The first window gets no events and the second+spy get up
4785 firstWindow->assertNoEvents();
4786 spyWindow->consumeMotionUp();
4787 secondWindow->consumeMotionUp();
4788}
4789
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004790TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004791 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004792
4793 PointF touchPoint = {10, 10};
4794
4795 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004796 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004797 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4798 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004799 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004800 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004801 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4802 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004803 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004804
4805 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004806 mDispatcher->onWindowInfosChanged(
4807 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004808
4809 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004810 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4811 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4812 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004813 // Only the first window should get the down event
4814 firstWindow->consumeMotionDown();
4815 secondWindow->assertNoEvents();
4816
4817 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004818 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4819 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004820 // Only the first window should get the pointer down event
4821 firstWindow->consumeMotionPointerDown(1);
4822 secondWindow->assertNoEvents();
4823
4824 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004825 TransferFunction f = GetParam();
4826 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4827 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004828 // The first window gets cancel and the second gets down and pointer down
4829 firstWindow->consumeMotionCancel();
4830 secondWindow->consumeMotionDown();
4831 secondWindow->consumeMotionPointerDown(1);
4832
4833 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004834 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4835 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004836 // The first window gets nothing and the second gets pointer up
4837 firstWindow->assertNoEvents();
4838 secondWindow->consumeMotionPointerUp(1);
4839
4840 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004841 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4842 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004843 // The first window gets nothing and the second gets up
4844 firstWindow->assertNoEvents();
4845 secondWindow->consumeMotionUp();
4846}
4847
Arthur Hungc539dbb2022-12-08 07:45:36 +00004848TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4850
4851 // Create a couple of windows
4852 sp<FakeWindowHandle> firstWindow =
4853 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4854 ADISPLAY_ID_DEFAULT);
4855 firstWindow->setDupTouchToWallpaper(true);
4856 sp<FakeWindowHandle> secondWindow =
4857 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4858 ADISPLAY_ID_DEFAULT);
4859 secondWindow->setDupTouchToWallpaper(true);
4860
4861 sp<FakeWindowHandle> wallpaper1 =
4862 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4863 wallpaper1->setIsWallpaper(true);
4864
4865 sp<FakeWindowHandle> wallpaper2 =
4866 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4867 wallpaper2->setIsWallpaper(true);
4868 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004869 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4870 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4871 {},
4872 0,
4873 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004874
4875 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004876 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4877 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004878
4879 // Only the first window should get the down event
4880 firstWindow->consumeMotionDown();
4881 secondWindow->assertNoEvents();
4882 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4883 wallpaper2->assertNoEvents();
4884
4885 // Transfer touch focus to the second window
4886 TransferFunction f = GetParam();
4887 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4888 ASSERT_TRUE(success);
4889
4890 // The first window gets cancel and the second gets down
4891 firstWindow->consumeMotionCancel();
4892 secondWindow->consumeMotionDown();
4893 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4894 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4895
4896 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004897 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4898 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004899 // The first window gets no events and the second gets up
4900 firstWindow->assertNoEvents();
4901 secondWindow->consumeMotionUp();
4902 wallpaper1->assertNoEvents();
4903 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4904}
4905
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004906// For the cases of single pointer touch and two pointers non-split touch, the api's
4907// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4908// for the case where there are multiple pointers split across several windows.
4909INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4910 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004911 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4912 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004913 return dispatcher->transferTouch(destChannelToken,
4914 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004915 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004916 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4917 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004918 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004919 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004920 }));
4921
Svet Ganov5d3bc372020-01-26 23:11:07 -08004922TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004924
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004925 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004926 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4927 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004928 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004929
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004930 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004931 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4932 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004933 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004934
4935 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004936 mDispatcher->onWindowInfosChanged(
4937 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004938
4939 PointF pointInFirst = {300, 200};
4940 PointF pointInSecond = {300, 600};
4941
4942 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004943 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4944 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4945 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004946 // Only the first window should get the down event
4947 firstWindow->consumeMotionDown();
4948 secondWindow->assertNoEvents();
4949
4950 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004951 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4952 ADISPLAY_ID_DEFAULT,
4953 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004954 // The first window gets a move and the second a down
4955 firstWindow->consumeMotionMove();
4956 secondWindow->consumeMotionDown();
4957
4958 // Transfer touch focus to the second window
4959 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4960 // The first window gets cancel and the new gets pointer down (it already saw down)
4961 firstWindow->consumeMotionCancel();
4962 secondWindow->consumeMotionPointerDown(1);
4963
4964 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004965 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4966 ADISPLAY_ID_DEFAULT,
4967 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004968 // The first window gets nothing and the second gets pointer up
4969 firstWindow->assertNoEvents();
4970 secondWindow->consumeMotionPointerUp(1);
4971
4972 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004973 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4974 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004975 // The first window gets nothing and the second gets up
4976 firstWindow->assertNoEvents();
4977 secondWindow->consumeMotionUp();
4978}
4979
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004980// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4981// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4982// touch is not supported, so the touch should continue on those windows and the transferred-to
4983// window should get nothing.
4984TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4985 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4986
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004987 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004988 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4989 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004990 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004991
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004992 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004993 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4994 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004995 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004996
4997 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004998 mDispatcher->onWindowInfosChanged(
4999 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005000
5001 PointF pointInFirst = {300, 200};
5002 PointF pointInSecond = {300, 600};
5003
5004 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005005 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5006 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5007 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005008 // Only the first window should get the down event
5009 firstWindow->consumeMotionDown();
5010 secondWindow->assertNoEvents();
5011
5012 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005013 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5014 ADISPLAY_ID_DEFAULT,
5015 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005016 // The first window gets a move and the second a down
5017 firstWindow->consumeMotionMove();
5018 secondWindow->consumeMotionDown();
5019
5020 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005021 const bool transferred =
5022 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005023 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5024 ASSERT_FALSE(transferred);
5025 firstWindow->assertNoEvents();
5026 secondWindow->assertNoEvents();
5027
5028 // The rest of the dispatch should proceed as normal
5029 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005030 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5031 ADISPLAY_ID_DEFAULT,
5032 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005033 // The first window gets MOVE and the second gets pointer up
5034 firstWindow->consumeMotionMove();
5035 secondWindow->consumeMotionUp();
5036
5037 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005038 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5039 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005040 // The first window gets nothing and the second gets up
5041 firstWindow->consumeMotionUp();
5042 secondWindow->assertNoEvents();
5043}
5044
Arthur Hungabbb9d82021-09-01 14:52:30 +00005045// This case will create two windows and one mirrored window on the default display and mirror
5046// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5047// the windows info of second display before default display.
5048TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5050 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005051 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005052 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005053 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005054 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005055 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005056
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005057 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005058 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005059
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005060 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005061 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005062
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005063 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005064 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005065
5066 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005067 mDispatcher->onWindowInfosChanged(
5068 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5069 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5070 *secondWindowInPrimary->getInfo()},
5071 {},
5072 0,
5073 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005074
5075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005077 {50, 50}))
5078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5079
5080 // Window should receive motion event.
5081 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5082
5083 // Transfer touch focus
5084 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5085 secondWindowInPrimary->getToken()));
5086 // The first window gets cancel.
5087 firstWindowInPrimary->consumeMotionCancel();
5088 secondWindowInPrimary->consumeMotionDown();
5089
5090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005091 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005092 ADISPLAY_ID_DEFAULT, {150, 50}))
5093 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5094 firstWindowInPrimary->assertNoEvents();
5095 secondWindowInPrimary->consumeMotionMove();
5096
5097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005098 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005099 {150, 50}))
5100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5101 firstWindowInPrimary->assertNoEvents();
5102 secondWindowInPrimary->consumeMotionUp();
5103}
5104
5105// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5106// 'transferTouch' api.
5107TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5109 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005110 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005111 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005112 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005113 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005114 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005115
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005116 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005117 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005118
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005119 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005120 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005121
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005122 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005123 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005124
5125 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005126 mDispatcher->onWindowInfosChanged(
5127 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5128 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5129 *secondWindowInPrimary->getInfo()},
5130 {},
5131 0,
5132 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005133
5134 // Touch on second display.
5135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005136 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5137 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005138 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5139
5140 // Window should receive motion event.
5141 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5142
5143 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005144 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005145
5146 // The first window gets cancel.
5147 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5148 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5149
5150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005151 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005152 SECOND_DISPLAY_ID, {150, 50}))
5153 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5154 firstWindowInPrimary->assertNoEvents();
5155 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5156
5157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005158 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5160 firstWindowInPrimary->assertNoEvents();
5161 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5162}
5163
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005164TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005166 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5167 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005168
Vishnu Nair47074b82020-08-14 11:54:47 -07005169 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005171 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005172
5173 window->consumeFocusEvent(true);
5174
Prabir Pradhan678438e2023-04-13 19:32:51 +00005175 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005176
5177 // Window should receive key down event.
5178 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005179
5180 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005181 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005182 mFakePolicy->assertUserActivityPoked();
5183}
5184
5185TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5187 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5188 "Fake Window", ADISPLAY_ID_DEFAULT);
5189
5190 window->setDisableUserActivity(true);
5191 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005192 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005193 setFocusedWindow(window);
5194
5195 window->consumeFocusEvent(true);
5196
5197 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5198
5199 // Window should receive key down event.
5200 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5201
5202 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005203 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005204 mFakePolicy->assertUserActivityNotPoked();
5205}
5206
5207TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5209 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5210 "Fake Window", ADISPLAY_ID_DEFAULT);
5211
5212 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005213 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005214 setFocusedWindow(window);
5215
5216 window->consumeFocusEvent(true);
5217
5218 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5219 mDispatcher->waitForIdle();
5220
5221 // System key is not passed down
5222 window->assertNoEvents();
5223
5224 // Should have poked user activity
5225 mFakePolicy->assertUserActivityPoked();
5226}
5227
5228TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5230 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5231 "Fake Window", ADISPLAY_ID_DEFAULT);
5232
5233 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005234 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005235 setFocusedWindow(window);
5236
5237 window->consumeFocusEvent(true);
5238
5239 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5240 mDispatcher->waitForIdle();
5241
5242 // System key is not passed down
5243 window->assertNoEvents();
5244
5245 // Should have poked user activity
5246 mFakePolicy->assertUserActivityPoked();
5247}
5248
5249TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5250 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5251 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5252 "Fake Window", ADISPLAY_ID_DEFAULT);
5253
5254 window->setDisableUserActivity(true);
5255 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005256 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005257 setFocusedWindow(window);
5258
5259 window->consumeFocusEvent(true);
5260
5261 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5262 mDispatcher->waitForIdle();
5263
5264 // System key is not passed down
5265 window->assertNoEvents();
5266
5267 // Should have poked user activity
5268 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005269}
5270
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005271TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5273 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5274 "Fake Window", ADISPLAY_ID_DEFAULT);
5275
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005276 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005277
5278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005279 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005280 ADISPLAY_ID_DEFAULT, {100, 100}))
5281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5282
5283 window->consumeMotionEvent(
5284 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5285
5286 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005287 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005288 mFakePolicy->assertUserActivityPoked();
5289}
5290
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005291TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005293 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5294 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005295
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005296 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005297
Prabir Pradhan678438e2023-04-13 19:32:51 +00005298 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005299 mDispatcher->waitForIdle();
5300
5301 window->assertNoEvents();
5302}
5303
5304// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5305TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005307 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5308 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005309
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005310 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005311
5312 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005313 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005314 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005315 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5316 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005317
5318 // Window should receive only the motion event
5319 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5320 window->assertNoEvents(); // Key event or focus event will not be received
5321}
5322
arthurhungea3f4fc2020-12-21 23:18:53 +08005323TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5325
arthurhungea3f4fc2020-12-21 23:18:53 +08005326 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005327 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5328 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005329 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005330
arthurhungea3f4fc2020-12-21 23:18:53 +08005331 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005332 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5333 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005334 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005335
5336 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005337 mDispatcher->onWindowInfosChanged(
5338 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005339
5340 PointF pointInFirst = {300, 200};
5341 PointF pointInSecond = {300, 600};
5342
5343 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005344 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5345 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5346 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005347 // Only the first window should get the down event
5348 firstWindow->consumeMotionDown();
5349 secondWindow->assertNoEvents();
5350
5351 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005352 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5353 ADISPLAY_ID_DEFAULT,
5354 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005355 // The first window gets a move and the second a down
5356 firstWindow->consumeMotionMove();
5357 secondWindow->consumeMotionDown();
5358
5359 // Send pointer cancel to the second window
5360 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005361 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005362 {pointInFirst, pointInSecond});
5363 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005364 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005365 // The first window gets move and the second gets cancel.
5366 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5367 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5368
5369 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005370 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5371 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005372 // The first window gets up and the second gets nothing.
5373 firstWindow->consumeMotionUp();
5374 secondWindow->assertNoEvents();
5375}
5376
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005377TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5379
5380 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005381 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005382 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005383 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5384 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5385 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5386
Harry Cutts33476232023-01-30 19:57:29 +00005387 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005388 window->assertNoEvents();
5389 mDispatcher->waitForIdle();
5390}
5391
chaviwd1c23182019-12-20 18:44:56 -08005392class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00005393public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005394 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005395 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07005396 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08005397 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07005398 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00005399 }
5400
chaviwd1c23182019-12-20 18:44:56 -08005401 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
5402
5403 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005404 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
5405 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08005406 }
5407
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005408 std::optional<int32_t> receiveEvent() {
5409 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
5410 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005411
5412 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
5413
chaviwd1c23182019-12-20 18:44:56 -08005414 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005415 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08005416 expectedDisplayId, expectedFlags);
5417 }
5418
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005419 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005420 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005421 expectedDisplayId, expectedFlags);
5422 }
5423
chaviwd1c23182019-12-20 18:44:56 -08005424 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005425 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08005426 expectedDisplayId, expectedFlags);
5427 }
5428
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005429 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005430 mInputReceiver->consumeMotionEvent(
5431 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
5432 WithDisplayId(expectedDisplayId),
5433 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005434 }
5435
Arthur Hungfbfa5722021-11-16 02:45:54 +00005436 void consumeMotionPointerDown(int32_t pointerIdx) {
5437 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
5438 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005439 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005440 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00005441 }
5442
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005443 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
Evan Rosky84f07f02021-04-16 10:42:42 -07005444
chaviwd1c23182019-12-20 18:44:56 -08005445 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5446
5447private:
5448 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005449};
5450
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005451using InputDispatcherMonitorTest = InputDispatcherTest;
5452
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005453/**
5454 * Two entities that receive touch: A window, and a global monitor.
5455 * The touch goes to the window, and then the window disappears.
5456 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5457 * for the monitor, as well.
5458 * 1. foregroundWindow
5459 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5460 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005461TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5463 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005464 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005465
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005466 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005467
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005468 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005470 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005471 {100, 200}))
5472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5473
5474 // Both the foreground window and the global monitor should receive the touch down
5475 window->consumeMotionDown();
5476 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5477
5478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005479 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005480 ADISPLAY_ID_DEFAULT, {110, 200}))
5481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5482
5483 window->consumeMotionMove();
5484 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5485
5486 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005487 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005488 window->consumeMotionCancel();
5489 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5490
5491 // If more events come in, there will be no more foreground window to send them to. This will
5492 // cause a cancel for the monitor, as well.
5493 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005494 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005495 ADISPLAY_ID_DEFAULT, {120, 200}))
5496 << "Injection should fail because the window was removed";
5497 window->assertNoEvents();
5498 // Global monitor now gets the cancel
5499 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5500}
5501
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005502TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005504 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5505 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005506 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005507
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005508 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005509
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005511 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005513 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005514 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005515}
5516
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005517TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5518 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005519
Chris Yea209fde2020-07-22 13:54:51 -07005520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005521 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5522 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005523 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005524
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005526 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005527 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005528 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005529 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005530
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005531 // Pilfer pointers from the monitor.
5532 // This should not do anything and the window should continue to receive events.
5533 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005534
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005536 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005537 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005539
5540 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5541 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005542}
5543
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005544TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005546 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5547 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005548 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005549 window->setWindowOffset(20, 40);
5550 window->setWindowTransform(0, 1, -1, 0);
5551
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005552 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005553
5554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005555 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5557 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5558 MotionEvent* event = monitor.consumeMotion();
5559 // Even though window has transform, gesture monitor must not.
5560 ASSERT_EQ(ui::Transform(), event->getTransform());
5561}
5562
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005563TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005565 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005566
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005567 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005568 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005569 << "Injection should fail if there is a monitor, but no touchable window";
5570 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005571}
5572
chaviw81e2bb92019-12-18 15:03:51 -08005573TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005575 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5576 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005577
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005578 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005579
5580 NotifyMotionArgs motionArgs =
5581 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5582 ADISPLAY_ID_DEFAULT);
5583
Prabir Pradhan678438e2023-04-13 19:32:51 +00005584 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005585 // Window should receive motion down event.
5586 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5587
5588 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005589 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005590 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5591 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5592 motionArgs.pointerCoords[0].getX() - 10);
5593
Prabir Pradhan678438e2023-04-13 19:32:51 +00005594 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005595 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005596 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005597}
5598
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005599/**
5600 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5601 * the device default right away. In the test scenario, we check both the default value,
5602 * and the action of enabling / disabling.
5603 */
5604TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005606 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5607 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005608 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005609
5610 // Set focused application.
5611 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005612 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005613
5614 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005615 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005616 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005617 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005618
5619 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005620 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005621 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005622 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005623
5624 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005625 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005626 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005627 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005628 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005629 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005630 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005631 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005632
5633 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005634 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005635 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005636 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005637
5638 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005639 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005640 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005641 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005642 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005643 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005644 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005645 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005646
5647 window->assertNoEvents();
5648}
5649
Gang Wange9087892020-01-07 12:17:14 -05005650TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005652 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5653 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005654
5655 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005656 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005657
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005659 setFocusedWindow(window);
5660
Harry Cutts33476232023-01-30 19:57:29 +00005661 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005662
Prabir Pradhan678438e2023-04-13 19:32:51 +00005663 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5664 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005665
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005666 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005667 ASSERT_NE(event, nullptr);
5668
5669 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5670 ASSERT_NE(verified, nullptr);
5671 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5672
5673 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5674 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5675 ASSERT_EQ(keyArgs.source, verified->source);
5676 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5677
5678 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5679
5680 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005681 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005682 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005683 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5684 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5685 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5686 ASSERT_EQ(0, verifiedKey.repeatCount);
5687}
5688
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005689TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005690 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005691 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5692 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005693
5694 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5695
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005696 ui::Transform transform;
5697 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5698
5699 gui::DisplayInfo displayInfo;
5700 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5701 displayInfo.transform = transform;
5702
Patrick Williamsd828f302023-04-28 17:52:08 -05005703 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005704
Prabir Pradhan678438e2023-04-13 19:32:51 +00005705 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005706 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5707 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005708 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005709
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005710 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005711 ASSERT_NE(event, nullptr);
5712
5713 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5714 ASSERT_NE(verified, nullptr);
5715 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5716
5717 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5718 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5719 EXPECT_EQ(motionArgs.source, verified->source);
5720 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5721
5722 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5723
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005724 const vec2 rawXY =
5725 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5726 motionArgs.pointerCoords[0].getXYValue());
5727 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5728 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005729 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005730 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005731 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005732 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5733 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5734}
5735
chaviw09c8d2d2020-08-24 15:48:26 -07005736/**
5737 * Ensure that separate calls to sign the same data are generating the same key.
5738 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5739 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5740 * tests.
5741 */
5742TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5743 KeyEvent event = getTestKeyEvent();
5744 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5745
5746 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5747 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5748 ASSERT_EQ(hmac1, hmac2);
5749}
5750
5751/**
5752 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5753 */
5754TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5755 KeyEvent event = getTestKeyEvent();
5756 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5757 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5758
5759 verifiedEvent.deviceId += 1;
5760 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5761
5762 verifiedEvent.source += 1;
5763 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5764
5765 verifiedEvent.eventTimeNanos += 1;
5766 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5767
5768 verifiedEvent.displayId += 1;
5769 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5770
5771 verifiedEvent.action += 1;
5772 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5773
5774 verifiedEvent.downTimeNanos += 1;
5775 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5776
5777 verifiedEvent.flags += 1;
5778 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5779
5780 verifiedEvent.keyCode += 1;
5781 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5782
5783 verifiedEvent.scanCode += 1;
5784 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5785
5786 verifiedEvent.metaState += 1;
5787 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5788
5789 verifiedEvent.repeatCount += 1;
5790 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5791}
5792
Vishnu Nair958da932020-08-21 17:12:37 -07005793TEST_F(InputDispatcherTest, SetFocusedWindow) {
5794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5795 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005796 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005797 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005798 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005799 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5800
5801 // Top window is also focusable but is not granted focus.
5802 windowTop->setFocusable(true);
5803 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005804 mDispatcher->onWindowInfosChanged(
5805 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005806 setFocusedWindow(windowSecond);
5807
5808 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005810 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005811
5812 // Focused window should receive event.
5813 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5814 windowTop->assertNoEvents();
5815}
5816
5817TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5819 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005820 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005821 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5822
5823 window->setFocusable(true);
5824 // Release channel for window is no longer valid.
5825 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005826 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005827 setFocusedWindow(window);
5828
5829 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005830 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005831
5832 // window channel is invalid, so it should not receive any input event.
5833 window->assertNoEvents();
5834}
5835
5836TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5837 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5838 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005839 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005840 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005841 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005844 setFocusedWindow(window);
5845
5846 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005847 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005848
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005849 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005850 window->assertNoEvents();
5851}
5852
5853TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5855 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005856 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005857 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005858 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005859 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5860
5861 windowTop->setFocusable(true);
5862 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005863 mDispatcher->onWindowInfosChanged(
5864 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005865 setFocusedWindow(windowTop);
5866 windowTop->consumeFocusEvent(true);
5867
Chavi Weingarten847e8512023-03-29 00:26:09 +00005868 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005869 mDispatcher->onWindowInfosChanged(
5870 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005871 windowSecond->consumeFocusEvent(true);
5872 windowTop->consumeFocusEvent(false);
5873
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005875 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005876
5877 // Focused window should receive event.
5878 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5879}
5880
Chavi Weingarten847e8512023-03-29 00:26:09 +00005881TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5883 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005884 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005885 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005886 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005887 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5888
5889 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005890 windowSecond->setFocusable(false);
5891 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005892 mDispatcher->onWindowInfosChanged(
5893 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005894 setFocusedWindow(windowTop);
5895 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005896
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005898 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005899
5900 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005901 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005902 windowSecond->assertNoEvents();
5903}
5904
5905TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5906 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5907 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005908 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005909 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005910 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5911 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005912 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5913
5914 window->setFocusable(true);
5915 previousFocusedWindow->setFocusable(true);
5916 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005917 mDispatcher->onWindowInfosChanged(
5918 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005919 setFocusedWindow(previousFocusedWindow);
5920 previousFocusedWindow->consumeFocusEvent(true);
5921
5922 // Requesting focus on invisible window takes focus from currently focused window.
5923 setFocusedWindow(window);
5924 previousFocusedWindow->consumeFocusEvent(false);
5925
5926 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005928 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5929 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005930
5931 // Window does not get focus event or key down.
5932 window->assertNoEvents();
5933
5934 // Window becomes visible.
5935 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005936 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005937
5938 // Window receives focus event.
5939 window->consumeFocusEvent(true);
5940 // Focused window receives key down.
5941 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5942}
5943
Vishnu Nair599f1412021-06-21 10:39:58 -07005944TEST_F(InputDispatcherTest, DisplayRemoved) {
5945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5946 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005947 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005948 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5949
5950 // window is granted focus.
5951 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005952 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005953 setFocusedWindow(window);
5954 window->consumeFocusEvent(true);
5955
5956 // When a display is removed window loses focus.
5957 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5958 window->consumeFocusEvent(false);
5959}
5960
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005961/**
5962 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5963 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5964 * of the 'slipperyEnterWindow'.
5965 *
5966 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5967 * a way so that the touched location is no longer covered by the top window.
5968 *
5969 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5970 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5971 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5972 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5973 * with ACTION_DOWN).
5974 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5975 * window moved itself away from the touched location and had Flag::SLIPPERY.
5976 *
5977 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5978 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5979 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5980 *
5981 * In this test, we ensure that the event received by the bottom window has
5982 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5983 */
5984TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005985 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005986 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005987
5988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5989 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5990
5991 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005992 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005993 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005994 // Make sure this one overlaps the bottom window
5995 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5996 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5997 // one. Windows with the same owner are not considered to be occluding each other.
5998 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5999
6000 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006001 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006002 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6003
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006004 mDispatcher->onWindowInfosChanged(
6005 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006006
6007 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006008 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6009 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6010 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006011 slipperyExitWindow->consumeMotionDown();
6012 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006013 mDispatcher->onWindowInfosChanged(
6014 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006015
Prabir Pradhan678438e2023-04-13 19:32:51 +00006016 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6017 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6018 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006019
6020 slipperyExitWindow->consumeMotionCancel();
6021
6022 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6023 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6024}
6025
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006026/**
6027 * Two windows, one on the left and another on the right. The left window is slippery. The right
6028 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6029 * touch moves from the left window into the right window, the gesture should continue to go to the
6030 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6031 * reproduces a crash.
6032 */
6033TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6035
6036 sp<FakeWindowHandle> leftSlipperyWindow =
6037 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6038 leftSlipperyWindow->setSlippery(true);
6039 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6040
6041 sp<FakeWindowHandle> rightDropTouchesWindow =
6042 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6043 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6044 rightDropTouchesWindow->setDropInput(true);
6045
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006046 mDispatcher->onWindowInfosChanged(
6047 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006048
6049 // Start touch in the left window
6050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6051 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6052 .build());
6053 leftSlipperyWindow->consumeMotionDown();
6054
6055 // And move it into the right window
6056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6057 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6058 .build());
6059
6060 // Since the right window isn't eligible to receive input, touch does not slip.
6061 // The left window continues to receive the gesture.
6062 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6063 rightDropTouchesWindow->assertNoEvents();
6064}
6065
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006066/**
6067 * A single window is on screen first. Touch is injected into that window. Next, a second window
6068 * appears. Since the first window is slippery, touch will move from the first window to the second.
6069 */
6070TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6072 sp<FakeWindowHandle> originalWindow =
6073 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6074 originalWindow->setFrame(Rect(0, 0, 200, 200));
6075 originalWindow->setSlippery(true);
6076
6077 sp<FakeWindowHandle> appearingWindow =
6078 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6079 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6080
6081 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6082
6083 // Touch down on the original window
6084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6085 injectMotionEvent(*mDispatcher,
6086 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6087 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6088 .build()));
6089 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6090
6091 // Now, a new window appears. This could be, for example, a notification shade that appears
6092 // after user starts to drag down on the launcher window.
6093 mDispatcher->onWindowInfosChanged(
6094 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6096 injectMotionEvent(*mDispatcher,
6097 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6098 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6099 .build()));
6100 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6101 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6103 injectMotionEvent(*mDispatcher,
6104 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6105 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6106 .build()));
6107 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6108
6109 originalWindow->assertNoEvents();
6110 appearingWindow->assertNoEvents();
6111}
6112
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006113TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006114 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6116
6117 sp<FakeWindowHandle> leftWindow =
6118 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6119 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006120 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006121
6122 sp<FakeWindowHandle> rightSpy =
6123 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6124 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006125 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006126 rightSpy->setSpy(true);
6127 rightSpy->setTrustedOverlay(true);
6128
6129 sp<FakeWindowHandle> rightWindow =
6130 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6131 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006132 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006133
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006134 mDispatcher->onWindowInfosChanged(
6135 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006136
6137 // Touch in the left window
6138 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6139 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6140 .build());
6141 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6142 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006143 ASSERT_NO_FATAL_FAILURE(
6144 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006145
6146 // Touch another finger over the right windows
6147 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6148 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6149 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6150 .build());
6151 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6152 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6153 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6154 mDispatcher->waitForIdle();
6155 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006156 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6157 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006158
6159 // Release finger over left window. The UP actions are not treated as device interaction.
6160 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6161 // is part of the UP action, we do not treat this as device interaction.
6162 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6163 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6164 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6165 .build());
6166 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6167 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6168 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6169 mDispatcher->waitForIdle();
6170 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6171
6172 // Move remaining finger
6173 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6174 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6175 .build());
6176 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6177 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6178 mDispatcher->waitForIdle();
6179 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006180 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006181
6182 // Release all fingers
6183 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6184 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6185 .build());
6186 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6187 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6188 mDispatcher->waitForIdle();
6189 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6190}
6191
6192TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6194
6195 sp<FakeWindowHandle> window =
6196 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6197 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006198 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006199
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006201 setFocusedWindow(window);
6202 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6203
6204 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6205 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6206 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006207 ASSERT_NO_FATAL_FAILURE(
6208 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006209
6210 // The UP actions are not treated as device interaction.
6211 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6212 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6213 mDispatcher->waitForIdle();
6214 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6215}
6216
Garfield Tan1c7bc862020-01-28 13:24:04 -08006217class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6218protected:
6219 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6220 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6221
Chris Yea209fde2020-07-22 13:54:51 -07006222 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006223 sp<FakeWindowHandle> mWindow;
6224
6225 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006226 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006227 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006228 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006229 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006230 ASSERT_EQ(OK, mDispatcher->start());
6231
6232 setUpWindow();
6233 }
6234
6235 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006236 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006237 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006238
Vishnu Nair47074b82020-08-14 11:54:47 -07006239 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006240 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006241 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006242 mWindow->consumeFocusEvent(true);
6243 }
6244
Chris Ye2ad95392020-09-01 13:44:44 -07006245 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006246 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006247 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006248 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006249 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006250
6251 // Window should receive key down event.
6252 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6253 }
6254
6255 void expectKeyRepeatOnce(int32_t repeatCount) {
6256 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006257 mWindow->consumeKeyEvent(
6258 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006259 }
6260
Chris Ye2ad95392020-09-01 13:44:44 -07006261 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006262 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006263 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006264 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006265 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006266
6267 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006268 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006269 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006270 }
6271};
6272
6273TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006274 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006275 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6276 expectKeyRepeatOnce(repeatCount);
6277 }
6278}
6279
6280TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006281 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006282 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6283 expectKeyRepeatOnce(repeatCount);
6284 }
Harry Cutts33476232023-01-30 19:57:29 +00006285 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006286 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006287 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6288 expectKeyRepeatOnce(repeatCount);
6289 }
6290}
6291
6292TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006293 sendAndConsumeKeyDown(/*deviceId=*/1);
6294 expectKeyRepeatOnce(/*repeatCount=*/1);
6295 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006296 mWindow->assertNoEvents();
6297}
6298
6299TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006300 sendAndConsumeKeyDown(/*deviceId=*/1);
6301 expectKeyRepeatOnce(/*repeatCount=*/1);
6302 sendAndConsumeKeyDown(/*deviceId=*/2);
6303 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006304 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006305 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006306 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006307 expectKeyRepeatOnce(/*repeatCount=*/2);
6308 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006309 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006310 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006311 mWindow->assertNoEvents();
6312}
6313
6314TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006315 sendAndConsumeKeyDown(/*deviceId=*/1);
6316 expectKeyRepeatOnce(/*repeatCount=*/1);
6317 sendAndConsumeKeyDown(/*deviceId=*/2);
6318 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006319 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006320 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006321 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006322 mWindow->assertNoEvents();
6323}
6324
liushenxiang42232912021-05-21 20:24:09 +08006325TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6326 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006327 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006328 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006329 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6330 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6331 mWindow->assertNoEvents();
6332}
6333
Garfield Tan1c7bc862020-01-28 13:24:04 -08006334TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006335 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006336 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006337 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006338 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006339 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6340 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6341 IdGenerator::getSource(repeatEvent->getId()));
6342 }
6343}
6344
6345TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006346 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006347 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006348
6349 std::unordered_set<int32_t> idSet;
6350 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006351 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006352 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6353 int32_t id = repeatEvent->getId();
6354 EXPECT_EQ(idSet.end(), idSet.find(id));
6355 idSet.insert(id);
6356 }
6357}
6358
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006359/* Test InputDispatcher for MultiDisplay */
6360class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6361public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006362 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006363 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006364
Chris Yea209fde2020-07-22 13:54:51 -07006365 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006366 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006367 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006368
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006369 // Set focus window for primary display, but focused display would be second one.
6370 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006371 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006372 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6373
Vishnu Nair958da932020-08-21 17:12:37 -07006374 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006375 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006376
Chris Yea209fde2020-07-22 13:54:51 -07006377 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006378 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006379 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006380 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006381 // Set focus display to second one.
6382 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6383 // Set focus window for second display.
6384 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006385 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006386 mDispatcher->onWindowInfosChanged(
6387 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006388 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006389 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006390 }
6391
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006392 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006393 InputDispatcherTest::TearDown();
6394
Chris Yea209fde2020-07-22 13:54:51 -07006395 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006396 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006397 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006398 windowInSecondary.clear();
6399 }
6400
6401protected:
Chris Yea209fde2020-07-22 13:54:51 -07006402 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006403 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006404 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006405 sp<FakeWindowHandle> windowInSecondary;
6406};
6407
6408TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6409 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006411 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006412 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006413 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006414 windowInSecondary->assertNoEvents();
6415
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006416 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006418 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006419 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006420 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006421 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006422}
6423
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006424TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006425 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006427 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006428 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006429 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006430 windowInSecondary->assertNoEvents();
6431
6432 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006434 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006435 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006436 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006437
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006438 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006439 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006440
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006441 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006442 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006443 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006444
6445 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006446 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006447 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006448 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006449 windowInSecondary->assertNoEvents();
6450}
6451
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006452// Test per-display input monitors for motion event.
6453TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006454 FakeMonitorReceiver monitorInPrimary =
6455 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6456 FakeMonitorReceiver monitorInSecondary =
6457 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006458
6459 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006461 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006463 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006464 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006465 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006466 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006467
6468 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006470 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006471 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006472 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006473 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006474 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006475 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006476
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006477 // Lift up the touch from the second display
6478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006479 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006480 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6481 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6482 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6483
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006484 // Test inject a non-pointer motion event.
6485 // If specific a display, it will dispatch to the focused window of particular display,
6486 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006488 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006490 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006491 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006492 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006493 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006494}
6495
6496// Test per-display input monitors for key event.
6497TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006498 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006499 FakeMonitorReceiver monitorInPrimary =
6500 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6501 FakeMonitorReceiver monitorInSecondary =
6502 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006503
6504 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006506 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006507 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006508 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006509 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006510 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006511}
6512
Vishnu Nair958da932020-08-21 17:12:37 -07006513TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6514 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006515 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006516 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006517 mDispatcher->onWindowInfosChanged(
6518 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6519 *windowInSecondary->getInfo()},
6520 {},
6521 0,
6522 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006523 setFocusedWindow(secondWindowInPrimary);
6524 windowInPrimary->consumeFocusEvent(false);
6525 secondWindowInPrimary->consumeFocusEvent(true);
6526
6527 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6529 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006530 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006531 windowInPrimary->assertNoEvents();
6532 windowInSecondary->assertNoEvents();
6533 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6534}
6535
Arthur Hungdfd528e2021-12-08 13:23:04 +00006536TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6537 FakeMonitorReceiver monitorInPrimary =
6538 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6539 FakeMonitorReceiver monitorInSecondary =
6540 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6541
6542 // Test touch down on primary display.
6543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006545 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6546 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6547 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6548
6549 // Test touch down on second display.
6550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006551 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6553 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6554 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6555
6556 // Trigger cancel touch.
6557 mDispatcher->cancelCurrentTouch();
6558 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6559 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6560 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6561 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6562
6563 // Test inject a move motion event, no window/monitor should receive the event.
6564 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006565 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006566 ADISPLAY_ID_DEFAULT, {110, 200}))
6567 << "Inject motion event should return InputEventInjectionResult::FAILED";
6568 windowInPrimary->assertNoEvents();
6569 monitorInPrimary.assertNoEvents();
6570
6571 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006572 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006573 SECOND_DISPLAY_ID, {110, 200}))
6574 << "Inject motion event should return InputEventInjectionResult::FAILED";
6575 windowInSecondary->assertNoEvents();
6576 monitorInSecondary.assertNoEvents();
6577}
6578
Jackal Guof9696682018-10-05 12:23:23 +08006579class InputFilterTest : public InputDispatcherTest {
6580protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006581 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6582 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006583 NotifyMotionArgs motionArgs;
6584
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006585 motionArgs =
6586 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006587 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006588 motionArgs =
6589 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006590 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006591 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006592 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006593 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006594 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006595 } else {
6596 mFakePolicy->assertFilterInputEventWasNotCalled();
6597 }
6598 }
6599
6600 void testNotifyKey(bool expectToBeFiltered) {
6601 NotifyKeyArgs keyArgs;
6602
6603 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006604 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006605 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006606 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006607 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006608
6609 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006610 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006611 } else {
6612 mFakePolicy->assertFilterInputEventWasNotCalled();
6613 }
6614 }
6615};
6616
6617// Test InputFilter for MotionEvent
6618TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6619 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006620 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6621 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006622
6623 // Enable InputFilter
6624 mDispatcher->setInputFilterEnabled(true);
6625 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006626 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6627 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006628
6629 // Disable InputFilter
6630 mDispatcher->setInputFilterEnabled(false);
6631 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006632 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6633 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006634}
6635
6636// Test InputFilter for KeyEvent
6637TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6638 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006639 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006640
6641 // Enable InputFilter
6642 mDispatcher->setInputFilterEnabled(true);
6643 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006644 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006645
6646 // Disable InputFilter
6647 mDispatcher->setInputFilterEnabled(false);
6648 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006649 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006650}
6651
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006652// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6653// logical display coordinate space.
6654TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6655 ui::Transform firstDisplayTransform;
6656 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6657 ui::Transform secondDisplayTransform;
6658 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6659
6660 std::vector<gui::DisplayInfo> displayInfos(2);
6661 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6662 displayInfos[0].transform = firstDisplayTransform;
6663 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6664 displayInfos[1].transform = secondDisplayTransform;
6665
Patrick Williamsd828f302023-04-28 17:52:08 -05006666 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006667
6668 // Enable InputFilter
6669 mDispatcher->setInputFilterEnabled(true);
6670
6671 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006672 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6673 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006674}
6675
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006676class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6677protected:
6678 virtual void SetUp() override {
6679 InputDispatcherTest::SetUp();
6680
6681 /**
6682 * We don't need to enable input filter to test the injected event policy, but we enabled it
6683 * here to make the tests more realistic, since this policy only matters when inputfilter is
6684 * on.
6685 */
6686 mDispatcher->setInputFilterEnabled(true);
6687
6688 std::shared_ptr<InputApplicationHandle> application =
6689 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006690 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6691 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006692
6693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6694 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006695 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006696 setFocusedWindow(mWindow);
6697 mWindow->consumeFocusEvent(true);
6698 }
6699
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006700 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6701 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006702 KeyEvent event;
6703
6704 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6705 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6706 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006707 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006708 const int32_t additionalPolicyFlags =
6709 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006711 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006712 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006713 policyFlags | additionalPolicyFlags));
6714
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006715 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006716 }
6717
6718 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6719 int32_t flags) {
6720 MotionEvent event;
6721 PointerProperties pointerProperties[1];
6722 PointerCoords pointerCoords[1];
6723 pointerProperties[0].clear();
6724 pointerProperties[0].id = 0;
6725 pointerCoords[0].clear();
6726 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6727 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6728
6729 ui::Transform identityTransform;
6730 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6731 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6732 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6733 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6734 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006735 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006736 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006737 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006738
6739 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006741 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006742 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006743 policyFlags | additionalPolicyFlags));
6744
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006745 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006746 }
6747
6748private:
6749 sp<FakeWindowHandle> mWindow;
6750};
6751
6752TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006753 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6754 // filter. Without it, the event will no different from a regularly injected event, and the
6755 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006756 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6757 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006758}
6759
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006760TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006761 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006762 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006763 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6764}
6765
6766TEST_F(InputFilterInjectionPolicyTest,
6767 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6768 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006769 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006770 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006771}
6772
6773TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006774 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6775 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006776}
6777
chaviwfd6d3512019-03-25 13:23:49 -07006778class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006779 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006780 InputDispatcherTest::SetUp();
6781
Chris Yea209fde2020-07-22 13:54:51 -07006782 std::shared_ptr<FakeApplicationHandle> application =
6783 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006784 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006785 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006786 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006787
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006788 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006789 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006790 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006791
6792 // Set focused application.
6793 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006794 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006795
6796 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006797 mDispatcher->onWindowInfosChanged(
6798 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006799 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006800 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006801 }
6802
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006803 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006804 InputDispatcherTest::TearDown();
6805
6806 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006807 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006808 }
6809
6810protected:
6811 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006812 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006813 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006814};
6815
6816// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6817// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6818// the onPointerDownOutsideFocus callback.
6819TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006821 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006822 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006824 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006825
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006826 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006827 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6828}
6829
6830// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6831// DOWN on the window that doesn't have focus. Ensure no window received the
6832// onPointerDownOutsideFocus callback.
6833TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6836 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006837 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006838 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006839
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006840 ASSERT_TRUE(mDispatcher->waitForIdle());
6841 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006842}
6843
6844// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6845// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6846TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006848 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006849 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006850 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006851
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006852 ASSERT_TRUE(mDispatcher->waitForIdle());
6853 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006854}
6855
6856// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6857// DOWN on the window that already has focus. Ensure no window received the
6858// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006859TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006861 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006862 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006864 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006865
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006866 ASSERT_TRUE(mDispatcher->waitForIdle());
6867 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006868}
6869
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006870// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6871// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6872TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6873 const MotionEvent event =
6874 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6875 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006876 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006877 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6878 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6881 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6882
6883 ASSERT_TRUE(mDispatcher->waitForIdle());
6884 mFakePolicy->assertOnPointerDownWasNotCalled();
6885 // Ensure that the unfocused window did not receive any FOCUS events.
6886 mUnfocusedWindow->assertNoEvents();
6887}
6888
chaviwaf87b3e2019-10-01 16:59:28 -07006889// These tests ensures we can send touch events to a single client when there are multiple input
6890// windows that point to the same client token.
6891class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6892 virtual void SetUp() override {
6893 InputDispatcherTest::SetUp();
6894
Chris Yea209fde2020-07-22 13:54:51 -07006895 std::shared_ptr<FakeApplicationHandle> application =
6896 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006897 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6898 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006899 mWindow1->setFrame(Rect(0, 0, 100, 100));
6900
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006901 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6902 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006903 mWindow2->setFrame(Rect(100, 100, 200, 200));
6904
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006905 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006906 }
6907
6908protected:
6909 sp<FakeWindowHandle> mWindow1;
6910 sp<FakeWindowHandle> mWindow2;
6911
6912 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006913 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006914 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6915 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006916 }
6917
6918 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6919 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006920 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006921 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006922
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006923 ASSERT_NE(nullptr, motionEvent)
6924 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006925
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006926 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006927 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006928
6929 for (size_t i = 0; i < points.size(); i++) {
6930 float expectedX = points[i].x;
6931 float expectedY = points[i].y;
6932
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006933 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006934 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006935 << ", got " << motionEvent->getX(i);
6936 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006937 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006938 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006939 }
6940 }
chaviw9eaa22c2020-07-01 16:21:27 -07006941
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006942 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006943 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006944 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6945 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006946
6947 // Always consume from window1 since it's the window that has the InputReceiver
6948 consumeMotionEvent(mWindow1, action, expectedPoints);
6949 }
chaviwaf87b3e2019-10-01 16:59:28 -07006950};
6951
6952TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6953 // Touch Window 1
6954 PointF touchedPoint = {10, 10};
6955 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006956 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006957
6958 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006959 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006960
6961 // Touch Window 2
6962 touchedPoint = {150, 150};
6963 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006964 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006965}
6966
chaviw9eaa22c2020-07-01 16:21:27 -07006967TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6968 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006969 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006970 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006971
6972 // Touch Window 1
6973 PointF touchedPoint = {10, 10};
6974 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006975 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006976 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006977 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006978
6979 // Touch Window 2
6980 touchedPoint = {150, 150};
6981 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006982 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6983 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006984
chaviw9eaa22c2020-07-01 16:21:27 -07006985 // Update the transform so rotation is set
6986 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006987 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006988 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6989 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006990}
6991
chaviw9eaa22c2020-07-01 16:21:27 -07006992TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006993 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006994 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006995
6996 // Touch Window 1
6997 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6998 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006999 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007000
7001 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007002 touchedPoints.push_back(PointF{150, 150});
7003 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007004 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007005
chaviw9eaa22c2020-07-01 16:21:27 -07007006 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007007 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007008 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007009
chaviw9eaa22c2020-07-01 16:21:27 -07007010 // Update the transform so rotation is set for Window 2
7011 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007012 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007013 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007014 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007015}
7016
chaviw9eaa22c2020-07-01 16:21:27 -07007017TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007018 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007019 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007020
7021 // Touch Window 1
7022 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7023 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007024 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007025
7026 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007027 touchedPoints.push_back(PointF{150, 150});
7028 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007029
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007030 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007031
7032 // Move both windows
7033 touchedPoints = {{20, 20}, {175, 175}};
7034 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7035 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7036
chaviw9eaa22c2020-07-01 16:21:27 -07007037 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007038
chaviw9eaa22c2020-07-01 16:21:27 -07007039 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007040 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007041 expectedPoints.pop_back();
7042
7043 // Touch Window 2
7044 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007045 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007046 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007047 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007048
7049 // Move both windows
7050 touchedPoints = {{20, 20}, {175, 175}};
7051 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7052 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7053
7054 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007055}
7056
7057TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7058 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007059 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007060
7061 // Touch Window 1
7062 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7063 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007064 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007065
7066 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007067 touchedPoints.push_back(PointF{150, 150});
7068 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007069
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007070 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007071
7072 // Move both windows
7073 touchedPoints = {{20, 20}, {175, 175}};
7074 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7075 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7076
chaviw9eaa22c2020-07-01 16:21:27 -07007077 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007078}
7079
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007080/**
7081 * When one of the windows is slippery, the touch should not slip into the other window with the
7082 * same input channel.
7083 */
7084TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7085 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007086 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007087
7088 // Touch down in window 1
7089 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7090 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7091 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7092
7093 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7094 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7095 // getting generated.
7096 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7097 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7098
7099 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7100}
7101
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007102/**
7103 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7104 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7105 * that the pointer is hovering over may have a different transform.
7106 */
7107TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007108 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007109
7110 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7112 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7113 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007114 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7115 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007116 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7118 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7119 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007120 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7121 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7122 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7123}
7124
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007125class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7126 virtual void SetUp() override {
7127 InputDispatcherTest::SetUp();
7128
Chris Yea209fde2020-07-22 13:54:51 -07007129 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007130 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007131 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7132 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007133 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007134 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007135 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007136
7137 // Set focused application.
7138 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7139
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007140 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007141 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007142 mWindow->consumeFocusEvent(true);
7143 }
7144
7145 virtual void TearDown() override {
7146 InputDispatcherTest::TearDown();
7147 mWindow.clear();
7148 }
7149
7150protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007151 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007152 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007153 sp<FakeWindowHandle> mWindow;
7154 static constexpr PointF WINDOW_LOCATION = {20, 20};
7155
7156 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007158 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007159 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007161 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007162 WINDOW_LOCATION));
7163 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007164
7165 sp<FakeWindowHandle> addSpyWindow() {
7166 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007167 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007168 spy->setTrustedOverlay(true);
7169 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007170 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007171 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007172 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007173 return spy;
7174 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007175};
7176
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007177// Send a tap and respond, which should not cause an ANR.
7178TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7179 tapOnWindow();
7180 mWindow->consumeMotionDown();
7181 mWindow->consumeMotionUp();
7182 ASSERT_TRUE(mDispatcher->waitForIdle());
7183 mFakePolicy->assertNotifyAnrWasNotCalled();
7184}
7185
7186// Send a regular key and respond, which should not cause an ANR.
7187TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007189 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7190 ASSERT_TRUE(mDispatcher->waitForIdle());
7191 mFakePolicy->assertNotifyAnrWasNotCalled();
7192}
7193
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007194TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7195 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007196 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007197 mWindow->consumeFocusEvent(false);
7198
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007199 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007200 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7201 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007202 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007204 // Key will not go to window because we have no focused window.
7205 // The 'no focused window' ANR timer should start instead.
7206
7207 // Now, the focused application goes away.
7208 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7209 // The key should get dropped and there should be no ANR.
7210
7211 ASSERT_TRUE(mDispatcher->waitForIdle());
7212 mFakePolicy->assertNotifyAnrWasNotCalled();
7213}
7214
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007215// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007216// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7217// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007218TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007220 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007221 WINDOW_LOCATION));
7222
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007223 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7224 ASSERT_TRUE(sequenceNum);
7225 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007226 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007227
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007228 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007229 mWindow->consumeMotionEvent(
7230 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007231 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007232 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007233}
7234
7235// Send a key to the app and have the app not respond right away.
7236TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7237 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007239 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7240 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007241 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007242 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007243 ASSERT_TRUE(mDispatcher->waitForIdle());
7244}
7245
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007246// We have a focused application, but no focused window
7247TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007248 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007249 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007250 mWindow->consumeFocusEvent(false);
7251
7252 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007254 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007255 WINDOW_LOCATION));
7256 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7257 mDispatcher->waitForIdle();
7258 mFakePolicy->assertNotifyAnrWasNotCalled();
7259
7260 // Once a focused event arrives, we get an ANR for this application
7261 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7262 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007263 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007264 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007265 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007266 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007267 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007268 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007269 ASSERT_TRUE(mDispatcher->waitForIdle());
7270}
7271
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007272/**
7273 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7274 * there will not be an ANR.
7275 */
7276TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7277 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007278 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007279 mWindow->consumeFocusEvent(false);
7280
7281 KeyEvent event;
7282 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7283 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7284
7285 // Define a valid key down event that is stale (too old).
7286 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007287 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007288 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007289
7290 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7291
7292 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007293 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007294 InputEventInjectionSync::WAIT_FOR_RESULT,
7295 INJECT_EVENT_TIMEOUT, policyFlags);
7296 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7297 << "Injection should fail because the event is stale";
7298
7299 ASSERT_TRUE(mDispatcher->waitForIdle());
7300 mFakePolicy->assertNotifyAnrWasNotCalled();
7301 mWindow->assertNoEvents();
7302}
7303
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007304// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007305// Make sure that we don't notify policy twice about the same ANR.
7306TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007307 const std::chrono::duration appTimeout = 400ms;
7308 mApplication->setDispatchingTimeout(appTimeout);
7309 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7310
Vishnu Nair47074b82020-08-14 11:54:47 -07007311 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007312 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007313 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007314
7315 // Once a focused event arrives, we get an ANR for this application
7316 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7317 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007318 const std::chrono::duration eventInjectionTimeout = 100ms;
7319 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007320 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007321 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007322 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7323 /*allowKeyRepeat=*/false);
7324 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7325 << "result=" << ftl::enum_string(result);
7326 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7327 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7328 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7329 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007330
Vishnu Naire4df8752022-09-08 09:17:55 -07007331 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007332 // ANR should not be raised again. It is up to policy to do that if it desires.
7333 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007334
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007335 // If we now get a focused window, the ANR should stop, but the policy handles that via
7336 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007337 ASSERT_TRUE(mDispatcher->waitForIdle());
7338}
7339
7340// We have a focused application, but no focused window
7341TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007342 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007343 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007344 mWindow->consumeFocusEvent(false);
7345
7346 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007347 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007348
Vishnu Naire4df8752022-09-08 09:17:55 -07007349 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7350 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007351
7352 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007353 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007354 ASSERT_TRUE(mDispatcher->waitForIdle());
7355 mWindow->assertNoEvents();
7356}
7357
7358/**
7359 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7360 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7361 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7362 * the ANR mechanism should still work.
7363 *
7364 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7365 * DOWN event, while not responding on the second one.
7366 */
7367TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7368 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007369 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007370 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7371 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7372 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007373 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007374
7375 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007376 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7378 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7379 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007380 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007381
7382 // We have now sent down and up. Let's consume first event and then ANR on the second.
7383 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7384 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007385 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007386}
7387
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007388// A spy window can receive an ANR
7389TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7390 sp<FakeWindowHandle> spy = addSpyWindow();
7391
7392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007393 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007394 WINDOW_LOCATION));
7395 mWindow->consumeMotionDown();
7396
7397 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7398 ASSERT_TRUE(sequenceNum);
7399 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007400 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007401
7402 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007403 spy->consumeMotionEvent(
7404 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007405 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007406 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007407}
7408
7409// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007410// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007411TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7412 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007413
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007415 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007416 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007418
7419 // Stuck on the ACTION_UP
7420 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007421 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007422
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007423 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007424 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007425 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7426 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007427
7428 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7429 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007430 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007431 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007432 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007433}
7434
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007435// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007436// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007437TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7438 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007439
7440 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007441 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7442 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007443
7444 mWindow->consumeMotionDown();
7445 // Stuck on the ACTION_UP
7446 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007447 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007448
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007449 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007450 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007451 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7452 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007453
7454 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7455 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007456 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007457 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007458 spy->assertNoEvents();
7459}
7460
7461TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007462 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007463
7464 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7465
7466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007468 WINDOW_LOCATION));
7469
7470 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7471 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7472 ASSERT_TRUE(consumeSeq);
7473
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007474 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7475 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007476
7477 monitor.finishEvent(*consumeSeq);
7478 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7479
7480 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007481 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007482}
7483
7484// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7485// process events, you don't get an anr. When the window later becomes unresponsive again, you
7486// get an ANR again.
7487// 1. tap -> block on ACTION_UP -> receive ANR
7488// 2. consume all pending events (= queue becomes healthy again)
7489// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7490TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7491 tapOnWindow();
7492
7493 mWindow->consumeMotionDown();
7494 // Block on 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 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7498 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007499 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007500 mWindow->assertNoEvents();
7501
7502 tapOnWindow();
7503 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007504 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007505 mWindow->consumeMotionUp();
7506
7507 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007508 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007509 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007510 mWindow->assertNoEvents();
7511}
7512
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007513// If a connection remains unresponsive for a while, make sure policy is only notified once about
7514// it.
7515TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007517 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007518 WINDOW_LOCATION));
7519
7520 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007521 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007522 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007523 // 'notifyConnectionUnresponsive' should only be called once per connection
7524 mFakePolicy->assertNotifyAnrWasNotCalled();
7525 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007526 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007527 mWindow->consumeMotionEvent(
7528 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007529 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007530 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007531 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007532 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007533}
7534
7535/**
7536 * 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 -07007537 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007538 *
7539 * Warning!!!
7540 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7541 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007542 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007543 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7544 *
7545 * If that value changes, this test should also change.
7546 */
7547TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7548 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007549 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007550
7551 tapOnWindow();
7552 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7553 ASSERT_TRUE(downSequenceNum);
7554 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7555 ASSERT_TRUE(upSequenceNum);
7556 // Don't finish the events yet, and send a key
7557 // Injection will "succeed" because we will eventually give up and send the key to the focused
7558 // window even if motions are still being processed. But because the injection timeout is short,
7559 // we will receive INJECTION_TIMED_OUT as the result.
7560
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007561 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007562 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7563 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007564 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007565 // Key will not be sent to the window, yet, because the window is still processing events
7566 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007567 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7568 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7569 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7570 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007571
7572 std::this_thread::sleep_for(500ms);
7573 // if we wait long enough though, dispatcher will give up, and still send the key
7574 // to the focused window, even though we have not yet finished the motion event
7575 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7576 mWindow->finishEvent(*downSequenceNum);
7577 mWindow->finishEvent(*upSequenceNum);
7578}
7579
7580/**
7581 * If a window is processing a motion event, and then a key event comes in, the key event should
7582 * not go to the focused window until the motion is processed.
7583 * If then a new motion comes in, then the pending key event should be going to the currently
7584 * focused window right away.
7585 */
7586TEST_F(InputDispatcherSingleWindowAnr,
7587 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7588 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007589 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007590
7591 tapOnWindow();
7592 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7593 ASSERT_TRUE(downSequenceNum);
7594 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7595 ASSERT_TRUE(upSequenceNum);
7596 // Don't finish the events yet, and send a key
7597 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007599 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7600 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007601 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007602 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7603 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7604 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7605 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007606
7607 // Now tap down again. It should cause the pending key to go to the focused window right away.
7608 tapOnWindow();
7609 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7610 // the other events yet. We can finish events in any order.
7611 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7612 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7613 mWindow->consumeMotionDown();
7614 mWindow->consumeMotionUp();
7615 mWindow->assertNoEvents();
7616}
7617
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007618/**
7619 * Send an event to the app and have the app not respond right away.
7620 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7621 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7622 * At some point, the window becomes responsive again.
7623 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7624 */
7625TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7627 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7628 .build());
7629
7630 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7631 ASSERT_TRUE(sequenceNum);
7632 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7633 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7634
7635 mWindow->finishEvent(*sequenceNum);
7636 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7637 ASSERT_TRUE(mDispatcher->waitForIdle());
7638 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7639
7640 // Now that the window is responsive, let's continue the gesture.
7641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7642 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7643 .build());
7644
7645 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7646 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7647 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7648 .build());
7649
7650 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7651 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7652 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7653 .build());
7654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7655 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7656 .build());
7657 // We already canceled this pointer, so the window shouldn't get any new events.
7658 mWindow->assertNoEvents();
7659
7660 // Start another one.
7661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7662 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7663 .build());
7664 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7665}
7666
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007667class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7668 virtual void SetUp() override {
7669 InputDispatcherTest::SetUp();
7670
Chris Yea209fde2020-07-22 13:54:51 -07007671 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007672 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007673 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7674 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007675 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007676 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007677 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007678
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007679 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7680 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007681 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007682 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007683
7684 // Set focused application.
7685 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007686 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007687
7688 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007689 mDispatcher->onWindowInfosChanged(
7690 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007691 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007692 mFocusedWindow->consumeFocusEvent(true);
7693 }
7694
7695 virtual void TearDown() override {
7696 InputDispatcherTest::TearDown();
7697
7698 mUnfocusedWindow.clear();
7699 mFocusedWindow.clear();
7700 }
7701
7702protected:
Chris Yea209fde2020-07-22 13:54:51 -07007703 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007704 sp<FakeWindowHandle> mUnfocusedWindow;
7705 sp<FakeWindowHandle> mFocusedWindow;
7706 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7707 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7708 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7709
7710 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7711
7712 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7713
7714private:
7715 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007718 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007720 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007721 location));
7722 }
7723};
7724
7725// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7726// should be ANR'd first.
7727TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007729 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007730 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007732 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007733 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007734 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007735 // We consumed all events, so no ANR
7736 ASSERT_TRUE(mDispatcher->waitForIdle());
7737 mFakePolicy->assertNotifyAnrWasNotCalled();
7738
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007740 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007741 FOCUSED_WINDOW_LOCATION));
7742 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7743 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007744
7745 const std::chrono::duration timeout =
7746 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007747 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007748 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7749 // sequence to make it consistent
7750 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007751 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007752 mFocusedWindow->consumeMotionDown();
7753 // This cancel is generated because the connection was unresponsive
7754 mFocusedWindow->consumeMotionCancel();
7755 mFocusedWindow->assertNoEvents();
7756 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007757 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007758 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7759 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007760 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007761}
7762
7763// If we have 2 windows with identical timeouts that are both unresponsive,
7764// it doesn't matter which order they should have ANR.
7765// But we should receive ANR for both.
7766TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7767 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007768 mUnfocusedWindow->setDispatchingTimeout(
7769 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007770 mDispatcher->onWindowInfosChanged(
7771 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007772
7773 tapOnFocusedWindow();
7774 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007775 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007776 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7777 mFocusedWindow->getDispatchingTimeout(
7778 DISPATCHING_TIMEOUT)),
7779 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7780
7781 ASSERT_THAT(anrConnectionTokens,
7782 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7783 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007784
7785 ASSERT_TRUE(mDispatcher->waitForIdle());
7786 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007787
7788 mFocusedWindow->consumeMotionDown();
7789 mFocusedWindow->consumeMotionUp();
7790 mUnfocusedWindow->consumeMotionOutside();
7791
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007792 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7793 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007794
7795 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007796 ASSERT_THAT(responsiveTokens,
7797 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7798 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007799 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007800}
7801
7802// If a window is already not responding, the second tap on the same window should be ignored.
7803// We should also log an error to account for the dropped event (not tested here).
7804// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7805TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7806 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007807 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007808 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007809 // Receive the events, but don't respond
7810 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7811 ASSERT_TRUE(downEventSequenceNum);
7812 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7813 ASSERT_TRUE(upEventSequenceNum);
7814 const std::chrono::duration timeout =
7815 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007816 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007817
7818 // Tap once again
7819 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007820 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007821 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007822 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007824 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007825 FOCUSED_WINDOW_LOCATION));
7826 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7827 // valid touch target
7828 mUnfocusedWindow->assertNoEvents();
7829
7830 // Consume the first tap
7831 mFocusedWindow->finishEvent(*downEventSequenceNum);
7832 mFocusedWindow->finishEvent(*upEventSequenceNum);
7833 ASSERT_TRUE(mDispatcher->waitForIdle());
7834 // The second tap did not go to the focused window
7835 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007836 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007837 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7838 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007839 mFakePolicy->assertNotifyAnrWasNotCalled();
7840}
7841
7842// If you tap outside of all windows, there will not be ANR
7843TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007844 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007845 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007846 LOCATION_OUTSIDE_ALL_WINDOWS));
7847 ASSERT_TRUE(mDispatcher->waitForIdle());
7848 mFakePolicy->assertNotifyAnrWasNotCalled();
7849}
7850
7851// Since the focused window is paused, tapping on it should not produce any events
7852TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7853 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007854 mDispatcher->onWindowInfosChanged(
7855 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007856
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007857 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007859 FOCUSED_WINDOW_LOCATION));
7860
7861 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7862 ASSERT_TRUE(mDispatcher->waitForIdle());
7863 // Should not ANR because the window is paused, and touches shouldn't go to it
7864 mFakePolicy->assertNotifyAnrWasNotCalled();
7865
7866 mFocusedWindow->assertNoEvents();
7867 mUnfocusedWindow->assertNoEvents();
7868}
7869
7870/**
7871 * 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 -07007872 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007873 * If a different window becomes focused at this time, the key should go to that window instead.
7874 *
7875 * Warning!!!
7876 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7877 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007878 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007879 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7880 *
7881 * If that value changes, this test should also change.
7882 */
7883TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7884 // Set a long ANR timeout to prevent it from triggering
7885 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007886 mDispatcher->onWindowInfosChanged(
7887 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007888
7889 tapOnUnfocusedWindow();
7890 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7891 ASSERT_TRUE(downSequenceNum);
7892 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7893 ASSERT_TRUE(upSequenceNum);
7894 // Don't finish the events yet, and send a key
7895 // Injection will succeed because we will eventually give up and send the key to the focused
7896 // window even if motions are still being processed.
7897
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007898 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007899 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7900 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007902 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007903 // and the key remains pending, waiting for the touch events to be processed.
7904 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7905 // under the hood.
7906 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7907 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007908
7909 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007910 mFocusedWindow->setFocusable(false);
7911 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007912 mDispatcher->onWindowInfosChanged(
7913 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007914 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007915
7916 // Focus events should precede the key events
7917 mUnfocusedWindow->consumeFocusEvent(true);
7918 mFocusedWindow->consumeFocusEvent(false);
7919
7920 // Finish the tap events, which should unblock dispatcher
7921 mUnfocusedWindow->finishEvent(*downSequenceNum);
7922 mUnfocusedWindow->finishEvent(*upSequenceNum);
7923
7924 // Now that all queues are cleared and no backlog in the connections, the key event
7925 // can finally go to the newly focused "mUnfocusedWindow".
7926 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7927 mFocusedWindow->assertNoEvents();
7928 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007929 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007930}
7931
7932// When the touch stream is split across 2 windows, and one of them does not respond,
7933// then ANR should be raised and the touch should be canceled for the unresponsive window.
7934// The other window should not be affected by that.
7935TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7936 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007937 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7938 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7939 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007940 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007941 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942
7943 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007944 mDispatcher->notifyMotion(
7945 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7946 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007947
7948 const std::chrono::duration timeout =
7949 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007950 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007951
7952 mUnfocusedWindow->consumeMotionDown();
7953 mFocusedWindow->consumeMotionDown();
7954 // Focused window may or may not receive ACTION_MOVE
7955 // But it should definitely receive ACTION_CANCEL due to the ANR
7956 InputEvent* event;
7957 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7958 ASSERT_TRUE(moveOrCancelSequenceNum);
7959 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7960 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007961 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007962 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7963 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7964 mFocusedWindow->consumeMotionCancel();
7965 } else {
7966 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7967 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007968 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007969 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7970 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007971
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007972 mUnfocusedWindow->assertNoEvents();
7973 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007974 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007975}
7976
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007977/**
7978 * If we have no focused window, and a key comes in, we start the ANR timer.
7979 * The focused application should add a focused window before the timer runs out to prevent ANR.
7980 *
7981 * If the user touches another application during this time, the key should be dropped.
7982 * Next, if a new focused window comes in, without toggling the focused application,
7983 * then no ANR should occur.
7984 *
7985 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7986 * but in some cases the policy may not update the focused application.
7987 */
7988TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7989 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7990 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07007991 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007992 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7993 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7994 mFocusedWindow->setFocusable(false);
7995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007996 mDispatcher->onWindowInfosChanged(
7997 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007998 mFocusedWindow->consumeFocusEvent(false);
7999
8000 // Send a key. The ANR timer should start because there is no focused window.
8001 // 'focusedApplication' will get blamed if this timer completes.
8002 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008003 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008004 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8005 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008006 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008008
8009 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8010 // then the injected touches won't cause the focused event to get dropped.
8011 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8012 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8013 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8014 // For this test, it means that the key would get delivered to the window once it becomes
8015 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008016 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008017
8018 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008019 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8020 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8021 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008022
8023 // We do not consume the motion right away, because that would require dispatcher to first
8024 // process (== drop) the key event, and by that time, ANR will be raised.
8025 // Set the focused window first.
8026 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008027 mDispatcher->onWindowInfosChanged(
8028 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008029 setFocusedWindow(mFocusedWindow);
8030 mFocusedWindow->consumeFocusEvent(true);
8031 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8032 // to another application. This could be a bug / behaviour in the policy.
8033
8034 mUnfocusedWindow->consumeMotionDown();
8035
8036 ASSERT_TRUE(mDispatcher->waitForIdle());
8037 // Should not ANR because we actually have a focused window. It was just added too slowly.
8038 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8039}
8040
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008041// These tests ensure we cannot send touch events to a window that's positioned behind a window
8042// that has feature NO_INPUT_CHANNEL.
8043// Layout:
8044// Top (closest to user)
8045// mNoInputWindow (above all windows)
8046// mBottomWindow
8047// Bottom (furthest from user)
8048class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8049 virtual void SetUp() override {
8050 InputDispatcherTest::SetUp();
8051
8052 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008053 mNoInputWindow =
8054 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8055 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008056 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008057 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008058 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8059 // It's perfectly valid for this window to not have an associated input channel
8060
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008061 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8062 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008063 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8064
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008065 mDispatcher->onWindowInfosChanged(
8066 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008067 }
8068
8069protected:
8070 std::shared_ptr<FakeApplicationHandle> mApplication;
8071 sp<FakeWindowHandle> mNoInputWindow;
8072 sp<FakeWindowHandle> mBottomWindow;
8073};
8074
8075TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8076 PointF touchedPoint = {10, 10};
8077
Prabir Pradhan678438e2023-04-13 19:32:51 +00008078 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8079 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8080 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008081
8082 mNoInputWindow->assertNoEvents();
8083 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8084 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8085 // and therefore should prevent mBottomWindow from receiving touches
8086 mBottomWindow->assertNoEvents();
8087}
8088
8089/**
8090 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8091 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8092 */
8093TEST_F(InputDispatcherMultiWindowOcclusionTests,
8094 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008095 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8096 "Window with input channel and NO_INPUT_CHANNEL",
8097 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008098
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008099 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008100 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008101 mDispatcher->onWindowInfosChanged(
8102 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008103
8104 PointF touchedPoint = {10, 10};
8105
Prabir Pradhan678438e2023-04-13 19:32:51 +00008106 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8107 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8108 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008109
8110 mNoInputWindow->assertNoEvents();
8111 mBottomWindow->assertNoEvents();
8112}
8113
Vishnu Nair958da932020-08-21 17:12:37 -07008114class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8115protected:
8116 std::shared_ptr<FakeApplicationHandle> mApp;
8117 sp<FakeWindowHandle> mWindow;
8118 sp<FakeWindowHandle> mMirror;
8119
8120 virtual void SetUp() override {
8121 InputDispatcherTest::SetUp();
8122 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008123 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8124 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8125 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008126 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8127 mWindow->setFocusable(true);
8128 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008129 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008130 }
8131};
8132
8133TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8134 // Request focus on a mirrored window
8135 setFocusedWindow(mMirror);
8136
8137 // window gets focused
8138 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008140 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008141 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8142}
8143
8144// A focused & mirrored window remains focused only if the window and its mirror are both
8145// focusable.
8146TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8147 setFocusedWindow(mMirror);
8148
8149 // window gets focused
8150 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008152 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008153 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008155 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008156 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8157
8158 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008159 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008160
8161 // window loses focus since one of the windows associated with the token in not focusable
8162 mWindow->consumeFocusEvent(false);
8163
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008164 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008165 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008166 mWindow->assertNoEvents();
8167}
8168
8169// A focused & mirrored window remains focused until the window and its mirror both become
8170// invisible.
8171TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8172 setFocusedWindow(mMirror);
8173
8174 // window gets focused
8175 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008177 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008178 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008180 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008181 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8182
8183 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008184 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008185
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008187 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008188 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008190 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008191 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8192
8193 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008194 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008195
8196 // window loses focus only after all windows associated with the token become invisible.
8197 mWindow->consumeFocusEvent(false);
8198
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008199 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008200 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008201 mWindow->assertNoEvents();
8202}
8203
8204// A focused & mirrored window remains focused until both windows are removed.
8205TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8206 setFocusedWindow(mMirror);
8207
8208 // window gets focused
8209 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008211 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008212 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008214 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008215 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8216
8217 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008218 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008219
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008221 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008222 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008224 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008225 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8226
8227 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008228 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008229 mWindow->consumeFocusEvent(false);
8230
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008231 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008232 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008233 mWindow->assertNoEvents();
8234}
8235
8236// Focus request can be pending until one window becomes visible.
8237TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8238 // Request focus on an invisible mirror.
8239 mWindow->setVisible(false);
8240 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008241 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008242 setFocusedWindow(mMirror);
8243
8244 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008246 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8247 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008248
8249 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008250 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008251
8252 // window gets focused
8253 mWindow->consumeFocusEvent(true);
8254 // window gets the pending key event
8255 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8256}
Prabir Pradhan99987712020-11-10 18:43:05 -08008257
8258class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8259protected:
8260 std::shared_ptr<FakeApplicationHandle> mApp;
8261 sp<FakeWindowHandle> mWindow;
8262 sp<FakeWindowHandle> mSecondWindow;
8263
8264 void SetUp() override {
8265 InputDispatcherTest::SetUp();
8266 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008267 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008268 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008269 mSecondWindow =
8270 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008271 mSecondWindow->setFocusable(true);
8272
8273 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008274 mDispatcher->onWindowInfosChanged(
8275 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008276
8277 setFocusedWindow(mWindow);
8278 mWindow->consumeFocusEvent(true);
8279 }
8280
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008281 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008282 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008283 }
8284
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008285 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8286 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008287 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008288 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8289 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008290 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008291 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008292 }
8293};
8294
8295TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8296 // Ensure that capture cannot be obtained for unfocused windows.
8297 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8298 mFakePolicy->assertSetPointerCaptureNotCalled();
8299 mSecondWindow->assertNoEvents();
8300
8301 // Ensure that capture can be enabled from the focus window.
8302 requestAndVerifyPointerCapture(mWindow, true);
8303
8304 // Ensure that capture cannot be disabled from a window that does not have capture.
8305 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8306 mFakePolicy->assertSetPointerCaptureNotCalled();
8307
8308 // Ensure that capture can be disabled from the window with capture.
8309 requestAndVerifyPointerCapture(mWindow, false);
8310}
8311
8312TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008313 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008314
8315 setFocusedWindow(mSecondWindow);
8316
8317 // Ensure that the capture disabled event was sent first.
8318 mWindow->consumeCaptureEvent(false);
8319 mWindow->consumeFocusEvent(false);
8320 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008321 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008322
8323 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008324 notifyPointerCaptureChanged({});
8325 notifyPointerCaptureChanged(request);
8326 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008327 mWindow->assertNoEvents();
8328 mSecondWindow->assertNoEvents();
8329 mFakePolicy->assertSetPointerCaptureNotCalled();
8330}
8331
8332TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008333 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008334
8335 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008336 notifyPointerCaptureChanged({});
8337 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008338
8339 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008340 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008341 mWindow->consumeCaptureEvent(false);
8342 mWindow->assertNoEvents();
8343}
8344
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008345TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8346 requestAndVerifyPointerCapture(mWindow, true);
8347
8348 // The first window loses focus.
8349 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008350 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008351 mWindow->consumeCaptureEvent(false);
8352
8353 // Request Pointer Capture from the second window before the notification from InputReader
8354 // arrives.
8355 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008356 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008357
8358 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008359 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008360
8361 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008362 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008363
8364 mSecondWindow->consumeFocusEvent(true);
8365 mSecondWindow->consumeCaptureEvent(true);
8366}
8367
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008368TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8369 // App repeatedly enables and disables capture.
8370 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8371 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8372 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8373 mFakePolicy->assertSetPointerCaptureCalled(false);
8374 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8375 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8376
8377 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8378 // first request is now stale, this should do nothing.
8379 notifyPointerCaptureChanged(firstRequest);
8380 mWindow->assertNoEvents();
8381
8382 // InputReader notifies that the second request was enabled.
8383 notifyPointerCaptureChanged(secondRequest);
8384 mWindow->consumeCaptureEvent(true);
8385}
8386
Prabir Pradhan7092e262022-05-03 16:51:09 +00008387TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8388 requestAndVerifyPointerCapture(mWindow, true);
8389
8390 // App toggles pointer capture off and on.
8391 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8392 mFakePolicy->assertSetPointerCaptureCalled(false);
8393
8394 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8395 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8396
8397 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8398 // preceding "disable" request.
8399 notifyPointerCaptureChanged(enableRequest);
8400
8401 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8402 // any notifications.
8403 mWindow->assertNoEvents();
8404}
8405
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008406/**
8407 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8408 * mouse movements don't affect the previous mouse hovering state.
8409 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8410 * HOVER_MOVE events).
8411 */
8412TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8413 // Mouse hover on the window
8414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8415 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8416 .build());
8417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8418 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8419 .build());
8420
8421 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8422 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8423
8424 // Start pointer capture
8425 requestAndVerifyPointerCapture(mWindow, true);
8426
8427 // Send some relative mouse movements and receive them in the window.
8428 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8429 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8430 .build());
8431 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8432 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8433
8434 // Stop pointer capture
8435 requestAndVerifyPointerCapture(mWindow, false);
8436
8437 // Continue hovering on the window
8438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8439 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8440 .build());
8441 mWindow->consumeMotionEvent(
8442 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8443
8444 mWindow->assertNoEvents();
8445}
8446
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008447class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8448protected:
8449 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008450
8451 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8452 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8453
8454 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8455 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8456
8457 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8458 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8459 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8460 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8461 MAXIMUM_OBSCURING_OPACITY);
8462
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008463 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8464 static constexpr gui::Uid APP_B_UID{10002};
8465 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008466
8467 sp<FakeWindowHandle> mTouchWindow;
8468
8469 virtual void SetUp() override {
8470 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008471 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008472 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8473 }
8474
8475 virtual void TearDown() override {
8476 InputDispatcherTest::TearDown();
8477 mTouchWindow.clear();
8478 }
8479
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008480 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008481 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008482 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008483 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008484 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008485 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008486 return window;
8487 }
8488
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008489 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008490 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8491 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008492 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008493 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008494 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008495 return window;
8496 }
8497
8498 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008499 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8500 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8501 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008502 }
8503};
8504
8505TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008506 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008507 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008508 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008509
8510 touch();
8511
8512 mTouchWindow->assertNoEvents();
8513}
8514
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008515TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008516 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8517 const sp<FakeWindowHandle>& w =
8518 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008519 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008520
8521 touch();
8522
8523 mTouchWindow->assertNoEvents();
8524}
8525
8526TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008527 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8528 const sp<FakeWindowHandle>& w =
8529 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008530 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008531
8532 touch();
8533
8534 w->assertNoEvents();
8535}
8536
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008537TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008538 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008539 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008540
8541 touch();
8542
8543 mTouchWindow->consumeAnyMotionDown();
8544}
8545
8546TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008547 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008548 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008549 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008550 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008551
8552 touch({PointF{100, 100}});
8553
8554 mTouchWindow->consumeAnyMotionDown();
8555}
8556
8557TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008558 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008559 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008560 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008561
8562 touch();
8563
8564 mTouchWindow->consumeAnyMotionDown();
8565}
8566
8567TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8568 const sp<FakeWindowHandle>& w =
8569 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008570 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008571
8572 touch();
8573
8574 mTouchWindow->consumeAnyMotionDown();
8575}
8576
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008577TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8578 const sp<FakeWindowHandle>& w =
8579 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008580 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008581
8582 touch();
8583
8584 w->assertNoEvents();
8585}
8586
8587/**
8588 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8589 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8590 * window, the occluding window will still receive ACTION_OUTSIDE event.
8591 */
8592TEST_F(InputDispatcherUntrustedTouchesTest,
8593 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8594 const sp<FakeWindowHandle>& w =
8595 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008596 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008597 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008598
8599 touch();
8600
8601 w->consumeMotionOutside();
8602}
8603
8604TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8605 const sp<FakeWindowHandle>& w =
8606 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008607 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008608 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008609
8610 touch();
8611
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008612 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008613}
8614
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008615TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008616 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008617 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8618 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008619 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008620
8621 touch();
8622
8623 mTouchWindow->consumeAnyMotionDown();
8624}
8625
8626TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8627 const sp<FakeWindowHandle>& w =
8628 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8629 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008630 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008631
8632 touch();
8633
8634 mTouchWindow->consumeAnyMotionDown();
8635}
8636
8637TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008638 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008639 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8640 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008641 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008642
8643 touch();
8644
8645 mTouchWindow->assertNoEvents();
8646}
8647
8648TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8649 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8650 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008651 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8652 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008653 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008654 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8655 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008656 mDispatcher->onWindowInfosChanged(
8657 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008658
8659 touch();
8660
8661 mTouchWindow->assertNoEvents();
8662}
8663
8664TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8665 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8666 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008667 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8668 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008669 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008670 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8671 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008672 mDispatcher->onWindowInfosChanged(
8673 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008674
8675 touch();
8676
8677 mTouchWindow->consumeAnyMotionDown();
8678}
8679
8680TEST_F(InputDispatcherUntrustedTouchesTest,
8681 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8682 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008683 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8684 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008685 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008686 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8687 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008688 mDispatcher->onWindowInfosChanged(
8689 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008690
8691 touch();
8692
8693 mTouchWindow->consumeAnyMotionDown();
8694}
8695
8696TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8697 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008698 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8699 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008700 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008701 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8702 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008703 mDispatcher->onWindowInfosChanged(
8704 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008705
8706 touch();
8707
8708 mTouchWindow->assertNoEvents();
8709}
8710
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008711TEST_F(InputDispatcherUntrustedTouchesTest,
8712 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8713 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008714 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8715 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008716 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008717 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8718 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008719 mDispatcher->onWindowInfosChanged(
8720 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008721
8722 touch();
8723
8724 mTouchWindow->assertNoEvents();
8725}
8726
8727TEST_F(InputDispatcherUntrustedTouchesTest,
8728 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8729 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008730 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8731 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008732 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008733 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8734 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008735 mDispatcher->onWindowInfosChanged(
8736 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008737
8738 touch();
8739
8740 mTouchWindow->consumeAnyMotionDown();
8741}
8742
8743TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8744 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008745 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8746 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008747 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008748
8749 touch();
8750
8751 mTouchWindow->consumeAnyMotionDown();
8752}
8753
8754TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8755 const sp<FakeWindowHandle>& w =
8756 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008757 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008758
8759 touch();
8760
8761 mTouchWindow->consumeAnyMotionDown();
8762}
8763
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008764TEST_F(InputDispatcherUntrustedTouchesTest,
8765 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8766 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8767 const sp<FakeWindowHandle>& w =
8768 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008769 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008770
8771 touch();
8772
8773 mTouchWindow->assertNoEvents();
8774}
8775
8776TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8777 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8778 const sp<FakeWindowHandle>& w =
8779 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008780 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008781
8782 touch();
8783
8784 mTouchWindow->consumeAnyMotionDown();
8785}
8786
8787TEST_F(InputDispatcherUntrustedTouchesTest,
8788 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8789 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8790 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008791 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8792 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008793 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008794
8795 touch();
8796
8797 mTouchWindow->consumeAnyMotionDown();
8798}
8799
8800TEST_F(InputDispatcherUntrustedTouchesTest,
8801 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8802 const sp<FakeWindowHandle>& w1 =
8803 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8804 OPACITY_BELOW_THRESHOLD);
8805 const sp<FakeWindowHandle>& w2 =
8806 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8807 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008808 mDispatcher->onWindowInfosChanged(
8809 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008810
8811 touch();
8812
8813 mTouchWindow->assertNoEvents();
8814}
8815
8816/**
8817 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8818 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8819 * (which alone would result in allowing touches) does not affect the blocking behavior.
8820 */
8821TEST_F(InputDispatcherUntrustedTouchesTest,
8822 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8823 const sp<FakeWindowHandle>& wB =
8824 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8825 OPACITY_BELOW_THRESHOLD);
8826 const sp<FakeWindowHandle>& wC =
8827 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8828 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008829 mDispatcher->onWindowInfosChanged(
8830 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008831
8832 touch();
8833
8834 mTouchWindow->assertNoEvents();
8835}
8836
8837/**
8838 * This test is testing that a window from a different UID but with same application token doesn't
8839 * block the touch. Apps can share the application token for close UI collaboration for example.
8840 */
8841TEST_F(InputDispatcherUntrustedTouchesTest,
8842 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8843 const sp<FakeWindowHandle>& w =
8844 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8845 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008846 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008847
8848 touch();
8849
8850 mTouchWindow->consumeAnyMotionDown();
8851}
8852
arthurhungb89ccb02020-12-30 16:19:01 +08008853class InputDispatcherDragTests : public InputDispatcherTest {
8854protected:
8855 std::shared_ptr<FakeApplicationHandle> mApp;
8856 sp<FakeWindowHandle> mWindow;
8857 sp<FakeWindowHandle> mSecondWindow;
8858 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008859 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008860 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8861 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008862
8863 void SetUp() override {
8864 InputDispatcherTest::SetUp();
8865 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008866 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008867 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008868
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008869 mSecondWindow =
8870 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008871 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008872
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008873 mSpyWindow =
8874 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008875 mSpyWindow->setSpy(true);
8876 mSpyWindow->setTrustedOverlay(true);
8877 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8878
arthurhungb89ccb02020-12-30 16:19:01 +08008879 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008880 mDispatcher->onWindowInfosChanged(
8881 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8882 {},
8883 0,
8884 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008885 }
8886
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008887 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8888 switch (fromSource) {
8889 case AINPUT_SOURCE_TOUCHSCREEN:
8890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008891 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008892 ADISPLAY_ID_DEFAULT, {50, 50}))
8893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8894 break;
8895 case AINPUT_SOURCE_STYLUS:
8896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008897 injectMotionEvent(*mDispatcher,
8898 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8899 AINPUT_SOURCE_STYLUS)
8900 .buttonState(
8901 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8902 .pointer(PointerBuilder(0, ToolType::STYLUS)
8903 .x(50)
8904 .y(50))
8905 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008906 break;
8907 case AINPUT_SOURCE_MOUSE:
8908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008909 injectMotionEvent(*mDispatcher,
8910 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8911 AINPUT_SOURCE_MOUSE)
8912 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8913 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8914 ToolType::MOUSE)
8915 .x(50)
8916 .y(50))
8917 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008918 break;
8919 default:
8920 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8921 }
arthurhungb89ccb02020-12-30 16:19:01 +08008922
8923 // Window should receive motion event.
8924 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008925 // Spy window should also receive motion event
8926 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008927 }
8928
8929 // Start performing drag, we will create a drag window and transfer touch to it.
8930 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8931 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008932 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008933 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008934 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008935 }
arthurhungb89ccb02020-12-30 16:19:01 +08008936
8937 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008938 mDragWindow =
8939 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008940 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008941 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8942 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8943 {},
8944 0,
8945 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008946
8947 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008948 bool transferred =
8949 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008950 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008951 if (transferred) {
8952 mWindow->consumeMotionCancel();
8953 mDragWindow->consumeMotionDown();
8954 }
8955 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008956 }
8957};
8958
8959TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008960 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008961
8962 // Move on window.
8963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008964 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008965 ADISPLAY_ID_DEFAULT, {50, 50}))
8966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8967 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8968 mWindow->consumeDragEvent(false, 50, 50);
8969 mSecondWindow->assertNoEvents();
8970
8971 // Move to another window.
8972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008973 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008974 ADISPLAY_ID_DEFAULT, {150, 50}))
8975 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8976 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8977 mWindow->consumeDragEvent(true, 150, 50);
8978 mSecondWindow->consumeDragEvent(false, 50, 50);
8979
8980 // Move back to original window.
8981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008982 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008983 ADISPLAY_ID_DEFAULT, {50, 50}))
8984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8985 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8986 mWindow->consumeDragEvent(false, 50, 50);
8987 mSecondWindow->consumeDragEvent(true, -50, 50);
8988
8989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008990 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8991 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08008992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8993 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8994 mWindow->assertNoEvents();
8995 mSecondWindow->assertNoEvents();
8996}
8997
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008998TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008999 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009000
9001 // No cancel event after drag start
9002 mSpyWindow->assertNoEvents();
9003
9004 const MotionEvent secondFingerDownEvent =
9005 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9006 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009007 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9008 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009009 .build();
9010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009011 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009012 InputEventInjectionSync::WAIT_FOR_RESULT))
9013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9014
9015 // Receives cancel for first pointer after next pointer down
9016 mSpyWindow->consumeMotionCancel();
9017 mSpyWindow->consumeMotionDown();
9018
9019 mSpyWindow->assertNoEvents();
9020}
9021
arthurhungf452d0b2021-01-06 00:19:52 +08009022TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009023 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009024
9025 // Move on window.
9026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009027 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009028 ADISPLAY_ID_DEFAULT, {50, 50}))
9029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9030 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9031 mWindow->consumeDragEvent(false, 50, 50);
9032 mSecondWindow->assertNoEvents();
9033
9034 // Move to another window.
9035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009036 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009037 ADISPLAY_ID_DEFAULT, {150, 50}))
9038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9039 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9040 mWindow->consumeDragEvent(true, 150, 50);
9041 mSecondWindow->consumeDragEvent(false, 50, 50);
9042
9043 // drop to another window.
9044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009045 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009046 {150, 50}))
9047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9048 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009049 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009050 mWindow->assertNoEvents();
9051 mSecondWindow->assertNoEvents();
9052}
9053
arthurhung6d4bed92021-03-17 11:59:33 +08009054TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009055 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009056
9057 // Move on window and keep button pressed.
9058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009059 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009060 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9061 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009062 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009063 .build()))
9064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9065 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9066 mWindow->consumeDragEvent(false, 50, 50);
9067 mSecondWindow->assertNoEvents();
9068
9069 // Move to another window and release button, expect to drop item.
9070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009071 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009072 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9073 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009074 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009075 .build()))
9076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9077 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9078 mWindow->assertNoEvents();
9079 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009080 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009081
9082 // nothing to the window.
9083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009084 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009085 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9086 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009087 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009088 .build()))
9089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9090 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9091 mWindow->assertNoEvents();
9092 mSecondWindow->assertNoEvents();
9093}
9094
Arthur Hung54745652022-04-20 07:17:41 +00009095TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009096 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009097
9098 // Set second window invisible.
9099 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009100 mDispatcher->onWindowInfosChanged(
9101 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009102
9103 // Move on window.
9104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009105 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009106 ADISPLAY_ID_DEFAULT, {50, 50}))
9107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9108 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9109 mWindow->consumeDragEvent(false, 50, 50);
9110 mSecondWindow->assertNoEvents();
9111
9112 // Move to another window.
9113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009114 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009115 ADISPLAY_ID_DEFAULT, {150, 50}))
9116 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9117 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9118 mWindow->consumeDragEvent(true, 150, 50);
9119 mSecondWindow->assertNoEvents();
9120
9121 // drop to another window.
9122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009123 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009124 {150, 50}))
9125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9126 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009127 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009128 mWindow->assertNoEvents();
9129 mSecondWindow->assertNoEvents();
9130}
9131
Arthur Hung54745652022-04-20 07:17:41 +00009132TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009133 // Ensure window could track pointerIds if it didn't support split touch.
9134 mWindow->setPreventSplitting(true);
9135
Arthur Hung54745652022-04-20 07:17:41 +00009136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009137 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009138 {50, 50}))
9139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9140 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9141
9142 const MotionEvent secondFingerDownEvent =
9143 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9144 .displayId(ADISPLAY_ID_DEFAULT)
9145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009146 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9147 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009148 .build();
9149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009150 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009151 InputEventInjectionSync::WAIT_FOR_RESULT))
9152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009153 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009154
9155 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009156 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009157}
9158
9159TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9160 // First down on second window.
9161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009162 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009163 {150, 50}))
9164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9165
9166 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9167
9168 // Second down on first window.
9169 const MotionEvent secondFingerDownEvent =
9170 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9171 .displayId(ADISPLAY_ID_DEFAULT)
9172 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009173 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9174 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009175 .build();
9176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009177 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009178 InputEventInjectionSync::WAIT_FOR_RESULT))
9179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9180 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9181
9182 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009183 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009184
9185 // Move on window.
9186 const MotionEvent secondFingerMoveEvent =
9187 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9188 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009189 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9190 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009191 .build();
9192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009193 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009194 InputEventInjectionSync::WAIT_FOR_RESULT));
9195 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9196 mWindow->consumeDragEvent(false, 50, 50);
9197 mSecondWindow->consumeMotionMove();
9198
9199 // Release the drag pointer should perform drop.
9200 const MotionEvent secondFingerUpEvent =
9201 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9202 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009203 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9204 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009205 .build();
9206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009207 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009208 InputEventInjectionSync::WAIT_FOR_RESULT));
9209 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009210 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009211 mWindow->assertNoEvents();
9212 mSecondWindow->consumeMotionMove();
9213}
9214
Arthur Hung3915c1f2022-05-31 07:17:17 +00009215TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009216 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009217
9218 // Update window of second display.
9219 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009220 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009221 mDispatcher->onWindowInfosChanged(
9222 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9223 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9224 {},
9225 0,
9226 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009227
9228 // Let second display has a touch state.
9229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009230 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009231 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9232 AINPUT_SOURCE_TOUCHSCREEN)
9233 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009234 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009235 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009236 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009237 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009238 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009239 mDispatcher->onWindowInfosChanged(
9240 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9241 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9242 {},
9243 0,
9244 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009245
9246 // Move on window.
9247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009248 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009249 ADISPLAY_ID_DEFAULT, {50, 50}))
9250 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9251 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9252 mWindow->consumeDragEvent(false, 50, 50);
9253 mSecondWindow->assertNoEvents();
9254
9255 // Move to another window.
9256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009257 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009258 ADISPLAY_ID_DEFAULT, {150, 50}))
9259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9260 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9261 mWindow->consumeDragEvent(true, 150, 50);
9262 mSecondWindow->consumeDragEvent(false, 50, 50);
9263
9264 // drop to another window.
9265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009266 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009267 {150, 50}))
9268 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9269 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009270 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009271 mWindow->assertNoEvents();
9272 mSecondWindow->assertNoEvents();
9273}
9274
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009275TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9276 startDrag(true, AINPUT_SOURCE_MOUSE);
9277 // Move on window.
9278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009279 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009280 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9281 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009282 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009283 .x(50)
9284 .y(50))
9285 .build()))
9286 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9287 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9288 mWindow->consumeDragEvent(false, 50, 50);
9289 mSecondWindow->assertNoEvents();
9290
9291 // Move to another window.
9292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009293 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009294 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9295 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009296 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009297 .x(150)
9298 .y(50))
9299 .build()))
9300 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9301 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9302 mWindow->consumeDragEvent(true, 150, 50);
9303 mSecondWindow->consumeDragEvent(false, 50, 50);
9304
9305 // drop to another window.
9306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009307 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009308 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9309 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009310 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009311 .x(150)
9312 .y(50))
9313 .build()))
9314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9315 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009316 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009317 mWindow->assertNoEvents();
9318 mSecondWindow->assertNoEvents();
9319}
9320
Vishnu Nair062a8672021-09-03 16:07:44 -07009321class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9322
9323TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009325 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9326 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009327 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009328 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9329 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009330 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009331 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009332 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009333
9334 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009335 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009336 window->assertNoEvents();
9337
Prabir Pradhan678438e2023-04-13 19:32:51 +00009338 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9339 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009340 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9341 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009342 window->assertNoEvents();
9343
9344 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009345 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009346 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009347
Prabir Pradhan678438e2023-04-13 19:32:51 +00009348 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009349 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9350
Prabir Pradhan678438e2023-04-13 19:32:51 +00009351 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9352 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009353 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9354 window->assertNoEvents();
9355}
9356
9357TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9358 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9359 std::make_shared<FakeApplicationHandle>();
9360 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009361 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9362 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009363 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009364 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009365 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009367 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9368 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009369 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009370 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009371 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9372 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009373 mDispatcher->onWindowInfosChanged(
9374 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009375 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009376 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009377
9378 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009379 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009380 window->assertNoEvents();
9381
Prabir Pradhan678438e2023-04-13 19:32:51 +00009382 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9383 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009384 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9385 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009386 window->assertNoEvents();
9387
9388 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009389 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009390 mDispatcher->onWindowInfosChanged(
9391 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009392
Prabir Pradhan678438e2023-04-13 19:32:51 +00009393 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009394 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9395
Prabir Pradhan678438e2023-04-13 19:32:51 +00009396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9397 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009398 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9399 window->assertNoEvents();
9400}
9401
9402TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9403 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9404 std::make_shared<FakeApplicationHandle>();
9405 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009406 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9407 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009408 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009409 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009410 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009412 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9413 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009414 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009415 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009416 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9417 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009418 mDispatcher->onWindowInfosChanged(
9419 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009420 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009421 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009422
9423 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009424 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009425 window->assertNoEvents();
9426
Prabir Pradhan678438e2023-04-13 19:32:51 +00009427 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9428 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009429 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9430 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009431 window->assertNoEvents();
9432
9433 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009434 mDispatcher->onWindowInfosChanged(
9435 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009436
Prabir Pradhan678438e2023-04-13 19:32:51 +00009437 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009438 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9439
Prabir Pradhan678438e2023-04-13 19:32:51 +00009440 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9441 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009442 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9443 window->assertNoEvents();
9444}
9445
Antonio Kantekf16f2832021-09-28 04:39:20 +00009446class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9447protected:
9448 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009449 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009450 sp<FakeWindowHandle> mWindow;
9451 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009452 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009453
9454 void SetUp() override {
9455 InputDispatcherTest::SetUp();
9456
9457 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009458 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009459 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009460 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009461 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009462 mSecondWindow =
9463 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009464 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009465 mThirdWindow =
9466 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9467 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9468 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009469
9470 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009471 mDispatcher->onWindowInfosChanged(
9472 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9473 {},
9474 0,
9475 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009476 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009477 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009478
Antonio Kantek15beb512022-06-13 22:35:41 +00009479 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009480 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009481 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009482 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9483 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009484 mThirdWindow->assertNoEvents();
9485 }
9486
9487 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9488 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009489 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009490 SECOND_DISPLAY_ID)) {
9491 mWindow->assertNoEvents();
9492 mSecondWindow->assertNoEvents();
9493 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009494 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009495 }
9496
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009497 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009498 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009499 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9500 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009501 mWindow->consumeTouchModeEvent(inTouchMode);
9502 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009503 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009504 }
9505};
9506
Antonio Kantek26defcf2022-02-08 01:12:27 +00009507TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009508 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009509 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9510 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009511 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009512}
9513
Antonio Kantek26defcf2022-02-08 01:12:27 +00009514TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9515 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009516 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009517 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009518 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009519 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009520 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009521 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009522 mWindow->assertNoEvents();
9523 mSecondWindow->assertNoEvents();
9524}
9525
9526TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9527 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009528 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009529 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009530 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009531 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009532 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009533}
9534
Antonio Kantekf16f2832021-09-28 04:39:20 +00009535TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009536 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009537 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9538 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009539 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009540 mWindow->assertNoEvents();
9541 mSecondWindow->assertNoEvents();
9542}
9543
Antonio Kantek15beb512022-06-13 22:35:41 +00009544TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9545 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9546 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9547 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009548 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009549 mWindow->assertNoEvents();
9550 mSecondWindow->assertNoEvents();
9551 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9552}
9553
Antonio Kantek48710e42022-03-24 14:19:30 -07009554TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9555 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9557 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009558 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9559 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9560
9561 // Then remove focus.
9562 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009563 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009564
9565 // Assert that caller can switch touch mode by owning one of the last interacted window.
9566 const WindowInfo& windowInfo = *mWindow->getInfo();
9567 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9568 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009569 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009570}
9571
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009572class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9573public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009574 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009575 std::shared_ptr<FakeApplicationHandle> application =
9576 std::make_shared<FakeApplicationHandle>();
9577 std::string name = "Fake Spy ";
9578 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009579 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9580 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009581 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009582 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009583 return spy;
9584 }
9585
9586 sp<FakeWindowHandle> createForeground() {
9587 std::shared_ptr<FakeApplicationHandle> application =
9588 std::make_shared<FakeApplicationHandle>();
9589 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009590 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9591 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009592 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009593 return window;
9594 }
9595
9596private:
9597 int mSpyCount{0};
9598};
9599
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009600using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009601/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009602 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9603 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009604TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009605 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009606 ScopedSilentDeath _silentDeath;
9607
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009608 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009609 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009610 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009611 ".* not a trusted overlay");
9612}
9613
9614/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009615 * Input injection into a display with a spy window but no foreground windows should succeed.
9616 */
9617TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009618 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009619 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009620
9621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009622 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9624 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9625}
9626
9627/**
9628 * Verify the order in which different input windows receive events. The touched foreground window
9629 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9630 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9631 * receive events before ones belows it.
9632 *
9633 * Here, we set up a scenario with four windows in the following Z order from the top:
9634 * spy1, spy2, window, spy3.
9635 * We then inject an event and verify that the foreground "window" receives it first, followed by
9636 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9637 * window.
9638 */
9639TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9640 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009641 auto spy1 = createSpy();
9642 auto spy2 = createSpy();
9643 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009644 mDispatcher->onWindowInfosChanged(
9645 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009646 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9647 const size_t numChannels = channels.size();
9648
Michael Wright8e9a8562022-02-09 13:44:29 +00009649 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009650 if (!epollFd.ok()) {
9651 FAIL() << "Failed to create epoll fd";
9652 }
9653
9654 for (size_t i = 0; i < numChannels; i++) {
9655 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9656 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9657 FAIL() << "Failed to add fd to epoll";
9658 }
9659 }
9660
9661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009662 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9664
9665 std::vector<size_t> eventOrder;
9666 std::vector<struct epoll_event> events(numChannels);
9667 for (;;) {
9668 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9669 (100ms).count());
9670 if (nFds < 0) {
9671 FAIL() << "Failed to call epoll_wait";
9672 }
9673 if (nFds == 0) {
9674 break; // epoll_wait timed out
9675 }
9676 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009677 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009678 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009679 channels[i]->consumeMotionDown();
9680 }
9681 }
9682
9683 // Verify the order in which the events were received.
9684 EXPECT_EQ(3u, eventOrder.size());
9685 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9686 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9687 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9688}
9689
9690/**
9691 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9692 */
9693TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9694 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009695 auto spy = createSpy();
9696 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009697 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009698
9699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9702 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9703 spy->assertNoEvents();
9704}
9705
9706/**
9707 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9708 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9709 * to the window.
9710 */
9711TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9712 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009713 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009714 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009715 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009716
9717 // Inject an event outside the spy window's touchable region.
9718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009719 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9721 window->consumeMotionDown();
9722 spy->assertNoEvents();
9723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009724 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9726 window->consumeMotionUp();
9727 spy->assertNoEvents();
9728
9729 // Inject an event inside the spy window's touchable region.
9730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009732 {5, 10}))
9733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9734 window->consumeMotionDown();
9735 spy->consumeMotionDown();
9736}
9737
9738/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009739 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009740 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009741 */
9742TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9743 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009744 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009745 auto spy = createSpy();
9746 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009747 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009748 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009749 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009750
9751 // Inject an event outside the spy window's frame and touchable region.
9752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009753 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009754 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9756 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009757 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009758}
9759
9760/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009761 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9762 * pointers that are down within its bounds.
9763 */
9764TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9765 auto windowLeft = createForeground();
9766 windowLeft->setFrame({0, 0, 100, 200});
9767 auto windowRight = createForeground();
9768 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009769 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009770 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009771 mDispatcher->onWindowInfosChanged(
9772 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009773
9774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009776 {50, 50}))
9777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9778 windowLeft->consumeMotionDown();
9779 spy->consumeMotionDown();
9780
9781 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009782 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009783 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009784 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9785 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009786 .build();
9787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009788 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009789 InputEventInjectionSync::WAIT_FOR_RESULT))
9790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9791 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009792 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009793}
9794
9795/**
9796 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9797 * the spy should receive the second pointer with ACTION_DOWN.
9798 */
9799TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9800 auto window = createForeground();
9801 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009802 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009803 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009804 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009805
9806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009807 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009808 {50, 50}))
9809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9810 window->consumeMotionDown();
9811 spyRight->assertNoEvents();
9812
9813 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009814 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009815 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009816 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9817 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009818 .build();
9819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009820 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009821 InputEventInjectionSync::WAIT_FOR_RESULT))
9822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009823 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009824 spyRight->consumeMotionDown();
9825}
9826
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009827/**
9828 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9829 * windows should be allowed to control split touch.
9830 */
9831TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009832 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009833 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009834 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009835 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009836
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009837 auto window = createForeground();
9838 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009839
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009840 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009841
9842 // First finger down, no window touched.
9843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009844 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009845 {100, 200}))
9846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9847 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9848 window->assertNoEvents();
9849
9850 // Second finger down on window, the window should receive touch down.
9851 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009852 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009853 .displayId(ADISPLAY_ID_DEFAULT)
9854 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009855 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9856 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009857 .build();
9858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009859 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009860 InputEventInjectionSync::WAIT_FOR_RESULT))
9861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9862
9863 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009864 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009865}
9866
9867/**
9868 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9869 * do not receive key events.
9870 */
9871TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009872 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009873 spy->setFocusable(false);
9874
9875 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009876 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009877 setFocusedWindow(window);
9878 window->consumeFocusEvent(true);
9879
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009881 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9882 window->consumeKeyDown(ADISPLAY_ID_NONE);
9883
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009885 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9886 window->consumeKeyUp(ADISPLAY_ID_NONE);
9887
9888 spy->assertNoEvents();
9889}
9890
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009891using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9892
9893/**
9894 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9895 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9896 */
9897TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9898 auto window = createForeground();
9899 auto spy1 = createSpy();
9900 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009901 mDispatcher->onWindowInfosChanged(
9902 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009903
9904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009905 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9907 window->consumeMotionDown();
9908 spy1->consumeMotionDown();
9909 spy2->consumeMotionDown();
9910
9911 // Pilfer pointers from the second spy window.
9912 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9913 spy2->assertNoEvents();
9914 spy1->consumeMotionCancel();
9915 window->consumeMotionCancel();
9916
9917 // The rest of the gesture should only be sent to the second spy window.
9918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009919 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009920 ADISPLAY_ID_DEFAULT))
9921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9922 spy2->consumeMotionMove();
9923 spy1->assertNoEvents();
9924 window->assertNoEvents();
9925}
9926
9927/**
9928 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9929 * in the middle of the gesture.
9930 */
9931TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9932 auto window = createForeground();
9933 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009934 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009935
9936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009937 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9939 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9940 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9941
9942 window->releaseChannel();
9943
9944 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9945
9946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009947 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009948 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9949 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9950}
9951
9952/**
9953 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9954 * the spy, but not to any other windows.
9955 */
9956TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9957 auto spy = createSpy();
9958 auto window = createForeground();
9959
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009960 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009961
9962 // First finger down on the window and the spy.
9963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009964 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009965 {100, 200}))
9966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9967 spy->consumeMotionDown();
9968 window->consumeMotionDown();
9969
9970 // Spy window pilfers the pointers.
9971 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9972 window->consumeMotionCancel();
9973
9974 // Second finger down on the window and spy, but the window should not receive the pointer down.
9975 const MotionEvent secondFingerDownEvent =
9976 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9977 .displayId(ADISPLAY_ID_DEFAULT)
9978 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009979 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9980 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009981 .build();
9982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009983 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009984 InputEventInjectionSync::WAIT_FOR_RESULT))
9985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9986
Harry Cutts33476232023-01-30 19:57:29 +00009987 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009988
9989 // Third finger goes down outside all windows, so injection should fail.
9990 const MotionEvent thirdFingerDownEvent =
9991 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9992 .displayId(ADISPLAY_ID_DEFAULT)
9993 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009994 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9995 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9996 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009997 .build();
9998 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009999 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010000 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010001 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010002
10003 spy->assertNoEvents();
10004 window->assertNoEvents();
10005}
10006
10007/**
10008 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10009 */
10010TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10011 auto spy = createSpy();
10012 spy->setFrame(Rect(0, 0, 100, 100));
10013 auto window = createForeground();
10014 window->setFrame(Rect(0, 0, 200, 200));
10015
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010016 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010017
10018 // First finger down on the window only
10019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010020 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010021 {150, 150}))
10022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10023 window->consumeMotionDown();
10024
10025 // Second finger down on the spy and window
10026 const MotionEvent secondFingerDownEvent =
10027 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10028 .displayId(ADISPLAY_ID_DEFAULT)
10029 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010030 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10031 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010032 .build();
10033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010034 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010035 InputEventInjectionSync::WAIT_FOR_RESULT))
10036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10037 spy->consumeMotionDown();
10038 window->consumeMotionPointerDown(1);
10039
10040 // Third finger down on the spy and window
10041 const MotionEvent thirdFingerDownEvent =
10042 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10043 .displayId(ADISPLAY_ID_DEFAULT)
10044 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010045 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10046 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10047 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010048 .build();
10049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010050 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010051 InputEventInjectionSync::WAIT_FOR_RESULT))
10052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10053 spy->consumeMotionPointerDown(1);
10054 window->consumeMotionPointerDown(2);
10055
10056 // Spy window pilfers the pointers.
10057 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010058 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10059 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010060
10061 spy->assertNoEvents();
10062 window->assertNoEvents();
10063}
10064
10065/**
10066 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10067 * other windows should be canceled. If this results in the cancellation of all pointers for some
10068 * window, then that window should receive ACTION_CANCEL.
10069 */
10070TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10071 auto spy = createSpy();
10072 spy->setFrame(Rect(0, 0, 100, 100));
10073 auto window = createForeground();
10074 window->setFrame(Rect(0, 0, 200, 200));
10075
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010076 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010077
10078 // First finger down on both spy and window
10079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010080 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010081 {10, 10}))
10082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10083 window->consumeMotionDown();
10084 spy->consumeMotionDown();
10085
10086 // Second finger down on the spy and window
10087 const MotionEvent secondFingerDownEvent =
10088 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10089 .displayId(ADISPLAY_ID_DEFAULT)
10090 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010091 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10092 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010093 .build();
10094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010095 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010096 InputEventInjectionSync::WAIT_FOR_RESULT))
10097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10098 spy->consumeMotionPointerDown(1);
10099 window->consumeMotionPointerDown(1);
10100
10101 // Spy window pilfers the pointers.
10102 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10103 window->consumeMotionCancel();
10104
10105 spy->assertNoEvents();
10106 window->assertNoEvents();
10107}
10108
10109/**
10110 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10111 * be sent to other windows
10112 */
10113TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10114 auto spy = createSpy();
10115 spy->setFrame(Rect(0, 0, 100, 100));
10116 auto window = createForeground();
10117 window->setFrame(Rect(0, 0, 200, 200));
10118
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010119 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010120
10121 // First finger down on both window and spy
10122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010123 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010124 {10, 10}))
10125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10126 window->consumeMotionDown();
10127 spy->consumeMotionDown();
10128
10129 // Spy window pilfers the pointers.
10130 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10131 window->consumeMotionCancel();
10132
10133 // Second finger down on the window only
10134 const MotionEvent secondFingerDownEvent =
10135 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10136 .displayId(ADISPLAY_ID_DEFAULT)
10137 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010138 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10139 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010140 .build();
10141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010142 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010143 InputEventInjectionSync::WAIT_FOR_RESULT))
10144 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10145 window->consumeMotionDown();
10146 window->assertNoEvents();
10147
10148 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10149 spy->consumeMotionMove();
10150 spy->assertNoEvents();
10151}
10152
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010153/**
10154 * A window on the left and a window on the right. Also, a spy window that's above all of the
10155 * windows, and spanning both left and right windows.
10156 * Send simultaneous motion streams from two different devices, one to the left window, and another
10157 * to the right window.
10158 * Pilfer from spy window.
10159 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10160 */
10161TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10162 sp<FakeWindowHandle> spy = createSpy();
10163 spy->setFrame(Rect(0, 0, 200, 200));
10164 sp<FakeWindowHandle> leftWindow = createForeground();
10165 leftWindow->setFrame(Rect(0, 0, 100, 100));
10166
10167 sp<FakeWindowHandle> rightWindow = createForeground();
10168 rightWindow->setFrame(Rect(100, 0, 200, 100));
10169
10170 constexpr int32_t stylusDeviceId = 1;
10171 constexpr int32_t touchDeviceId = 2;
10172
10173 mDispatcher->onWindowInfosChanged(
10174 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10175
10176 // Stylus down on left window and spy
10177 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10178 .deviceId(stylusDeviceId)
10179 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10180 .build());
10181 leftWindow->consumeMotionEvent(
10182 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10183 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10184
10185 // Finger down on right window and spy - but spy already has stylus
10186 mDispatcher->notifyMotion(
10187 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10188 .deviceId(touchDeviceId)
10189 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10190 .build());
10191 rightWindow->consumeMotionEvent(
10192 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10193 leftWindow->consumeMotionEvent(
10194 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10195 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10196 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10197
10198 // Act: pilfer from spy. Spy is currently receiving touch events.
10199 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10200 rightWindow->consumeMotionEvent(
10201 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10202
10203 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10204 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10205 .deviceId(stylusDeviceId)
10206 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10207 .build());
10208 mDispatcher->notifyMotion(
10209 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10210 .deviceId(touchDeviceId)
10211 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10212 .build());
10213 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10214
10215 spy->assertNoEvents();
10216 leftWindow->assertNoEvents();
10217 rightWindow->assertNoEvents();
10218}
10219
Prabir Pradhand65552b2021-10-07 11:23:50 -070010220class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10221public:
10222 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10223 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10224 std::make_shared<FakeApplicationHandle>();
10225 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010226 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10227 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010228 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010229 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010230 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010231 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010232 overlay->setTrustedOverlay(true);
10233
10234 std::shared_ptr<FakeApplicationHandle> application =
10235 std::make_shared<FakeApplicationHandle>();
10236 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010237 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10238 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010239 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010240 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010241
10242 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010243 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010244 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010245 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010246 return {std::move(overlay), std::move(window)};
10247 }
10248
10249 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010250 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010251 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010252 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010253 }
10254
10255 void sendStylusEvent(int32_t action) {
10256 NotifyMotionArgs motionArgs =
10257 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10258 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010259 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010260 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010261 }
10262};
10263
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010264using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10265
10266TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010267 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010268 ScopedSilentDeath _silentDeath;
10269
Prabir Pradhand65552b2021-10-07 11:23:50 -070010270 auto [overlay, window] = setupStylusOverlayScenario();
10271 overlay->setTrustedOverlay(false);
10272 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010273 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10274 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010275 ".* not a trusted overlay");
10276}
10277
10278TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10279 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010280 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010281
10282 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10283 overlay->consumeMotionDown();
10284 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10285 overlay->consumeMotionUp();
10286
10287 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10288 window->consumeMotionDown();
10289 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10290 window->consumeMotionUp();
10291
10292 overlay->assertNoEvents();
10293 window->assertNoEvents();
10294}
10295
10296TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10297 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010298 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010299 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010300
10301 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10302 overlay->consumeMotionDown();
10303 window->consumeMotionDown();
10304 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10305 overlay->consumeMotionUp();
10306 window->consumeMotionUp();
10307
10308 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10309 window->consumeMotionDown();
10310 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10311 window->consumeMotionUp();
10312
10313 overlay->assertNoEvents();
10314 window->assertNoEvents();
10315}
10316
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010317/**
10318 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10319 * The scenario is as follows:
10320 * - The stylus interceptor overlay is configured as a spy window.
10321 * - The stylus interceptor spy receives the start of a new stylus gesture.
10322 * - It pilfers pointers and then configures itself to no longer be a spy.
10323 * - The stylus interceptor continues to receive the rest of the gesture.
10324 */
10325TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10326 auto [overlay, window] = setupStylusOverlayScenario();
10327 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010328 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010329
10330 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10331 overlay->consumeMotionDown();
10332 window->consumeMotionDown();
10333
10334 // The interceptor pilfers the pointers.
10335 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10336 window->consumeMotionCancel();
10337
10338 // The interceptor configures itself so that it is no longer a spy.
10339 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010340 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010341
10342 // It continues to receive the rest of the stylus gesture.
10343 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10344 overlay->consumeMotionMove();
10345 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10346 overlay->consumeMotionUp();
10347
10348 window->assertNoEvents();
10349}
10350
Prabir Pradhan5735a322022-04-11 17:23:34 +000010351struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010352 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010353 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010354 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10355 std::unique_ptr<InputDispatcher>& mDispatcher;
10356
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010357 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010358 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10359
10360 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010361 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010362 ADISPLAY_ID_DEFAULT, {100, 200},
10363 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10364 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10365 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10366 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10367 }
10368
10369 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010370 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010371 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010372 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010373 mPolicyFlags);
10374 }
10375
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010376 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010377 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10378 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010379 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10380 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010381 window->setOwnerInfo(mPid, mUid);
10382 return window;
10383 }
10384};
10385
10386using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10387
10388TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010389 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010390 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010392
10393 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10394 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10395 window->consumeMotionDown();
10396
10397 setFocusedWindow(window);
10398 window->consumeFocusEvent(true);
10399
10400 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10401 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10402 window->consumeKeyDown(ADISPLAY_ID_NONE);
10403}
10404
10405TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010406 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010407 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010408 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010409
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010410 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010411 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10412 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10413
10414 setFocusedWindow(window);
10415 window->consumeFocusEvent(true);
10416
10417 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10418 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10419 window->assertNoEvents();
10420}
10421
10422TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010423 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010424 auto window = owner.createWindow("Owned window");
10425 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010426 spy->setSpy(true);
10427 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010428 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010429
10430 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10431 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10432 spy->consumeMotionDown();
10433 window->consumeMotionDown();
10434}
10435
10436TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010437 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010438 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010440 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010441 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010442 randosSpy->setSpy(true);
10443 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010444 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010445
10446 // The event is targeted at owner's window, so injection should succeed, but the spy should
10447 // not receive the event.
10448 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10449 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10450 randosSpy->assertNoEvents();
10451 window->consumeMotionDown();
10452}
10453
10454TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010455 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010456 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010457
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010458 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010459 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010460 randosSpy->setSpy(true);
10461 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010462 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010463
10464 // A user that has injection permission can inject into any window.
10465 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010466 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010467 ADISPLAY_ID_DEFAULT));
10468 randosSpy->consumeMotionDown();
10469 window->consumeMotionDown();
10470
10471 setFocusedWindow(randosSpy);
10472 randosSpy->consumeFocusEvent(true);
10473
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010474 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010475 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10476 window->assertNoEvents();
10477}
10478
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010479TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010480 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010481 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010483 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010484 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010485 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10486 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010487 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010488
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010489 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010490 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10491 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10492 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010493 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010494}
10495
Garfield Tane84e6f92019-08-29 17:28:41 -070010496} // namespace android::inputdispatcher