blob: e8b04b3cabffb0ebd5c36b031c3578ab2af7fc71 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070019#include "TestInputListenerMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Cody Heiner166a5af2023-07-07 12:25:00 -070021#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070022#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080023#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080024#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070025#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070026#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000027#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080028#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080029#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070031#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080032#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080033#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034
Garfield Tan1c7bc862020-01-28 13:24:04 -080035#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080036#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070037#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080038#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080039#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040
Garfield Tan1c7bc862020-01-28 13:24:04 -080041using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050042using android::gui::FocusRequest;
43using android::gui::TouchOcclusionMode;
44using android::gui::WindowInfo;
45using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080046using android::os::InputEventInjectionResult;
47using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080048
Garfield Tane84e6f92019-08-29 17:28:41 -070049namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080050
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080052using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070053
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070054namespace {
55
Michael Wrightd02c5b62014-02-10 15:10:22 -080056// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000057static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
59// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000060static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080061static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080062
Jeff Brownf086ddb2014-02-11 14:28:48 -080063// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000064static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
65static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080066
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000067// Ensure common actions are interchangeable between keys and motions for convenience.
68static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
69static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080070static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
71static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
72static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
73static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070074static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070076static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080077static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080078static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080079/**
80 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
81 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
82 * index 0) is the new pointer going down. The same pointer could have been placed at a different
83 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
84 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
85 * pointer id=0 leaves but the pointer id=1 remains.
86 */
87static constexpr int32_t POINTER_0_DOWN =
88 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080089static constexpr int32_t POINTER_1_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000091static constexpr int32_t POINTER_2_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000093static constexpr int32_t POINTER_3_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000095static constexpr int32_t POINTER_0_UP =
96 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080097static constexpr int32_t POINTER_1_UP =
98 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000099static constexpr int32_t POINTER_2_UP =
100 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800101
Antonio Kantek15beb512022-06-13 22:35:41 +0000102// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000103static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000104static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000105
Antonio Kantek15beb512022-06-13 22:35:41 +0000106// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000107static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000108static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000109
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000110// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000111static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000112
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800113static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
114
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700115/**
116 * If we expect to receive the event, the timeout can be made very long. When the test are running
117 * correctly, we will actually never wait until the end of the timeout because the wait will end
118 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
119 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
120 * developer can see the failure quickly (on human scale).
121 */
122static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
123/**
124 * When no event is expected, we can have a very short timeout. A large value here would slow down
125 * the tests. In the unlikely event of system being too slow, the event may still be present but the
126 * timeout would complete before it is consumed. This would result in test flakiness. If this
127 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
128 * would get noticed and addressed quickly.
129 */
130static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
131
Arthur Hungc539dbb2022-12-08 07:45:36 +0000132static constexpr int expectedWallpaperFlags =
133 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
134
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800135using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
136
chaviwd1c23182019-12-20 18:44:56 -0800137struct PointF {
138 float x;
139 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800140 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800141};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800142
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700143inline std::string pointFToString(const PointF& p) {
144 return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
145}
146
Gang Wang342c9272020-01-13 13:15:04 -0500147/**
148 * Return a DOWN key event with KEYCODE_A.
149 */
150static KeyEvent getTestKeyEvent() {
151 KeyEvent event;
152
Garfield Tanfbe732e2020-01-24 11:26:14 -0800153 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
154 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
155 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500156 return event;
157}
158
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800159MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700160 *result_listener << "expected downTime " << downTime << ", but got " << arg.getDownTime();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800161 return arg.getDownTime() == downTime;
162}
163
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800164MATCHER_P(WithSource, source, "InputEvent with specified source") {
165 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
166 << inputEventSourceToString(arg.getSource());
167 return arg.getSource() == source;
168}
169
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800170MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171 *result_listener << "expected flags " << std::hex << flags << ", but got " << arg.getFlags();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800172 return arg.getFlags() == flags;
173}
174
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800175MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
176 if (arg.getPointerCount() != 1) {
177 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
178 return false;
179 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700180 const float receivedX = arg.getX(/*pointerIndex=*/0);
181 const float receivedY = arg.getY(/*pointerIndex=*/0);
182 *result_listener << "expected coords (" << x << ", " << y << "), but got (" << receivedX << ", "
183 << receivedY << ")";
184 return receivedX == x && receivedY == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800185}
186
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800187MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700188 *result_listener << "expected pointerCount " << pointerCount << ", but got "
189 << arg.getPointerCount();
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800190 return arg.getPointerCount() == pointerCount;
191}
192
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800193MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
194 // Build a map for the received pointers, by pointer id
195 std::map<int32_t /*pointerId*/, PointF> actualPointers;
196 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
197 const int32_t pointerId = arg.getPointerId(pointerIndex);
198 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
199 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700200 *result_listener << "expected pointers " << dumpMap(pointers, constToString, pointFToString)
201 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800202 return pointers == actualPointers;
203}
204
Michael Wrightd02c5b62014-02-10 15:10:22 -0800205// --- FakeInputDispatcherPolicy ---
206
207class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000208 struct AnrResult {
209 sp<IBinder> token{};
210 gui::Pid pid{gui::Pid::INVALID};
211 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800212
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000214 FakeInputDispatcherPolicy() = default;
215 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800216
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800217 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700218 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700219 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700220 EXPECT_EQ(event.getDisplayId(), args.displayId);
221
222 const auto& keyEvent = static_cast<const KeyEvent&>(event);
223 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
224 EXPECT_EQ(keyEvent.getAction(), args.action);
225 });
Jackal Guof9696682018-10-05 12:23:23 +0800226 }
227
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
229 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700230 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700231 EXPECT_EQ(event.getDisplayId(), args.displayId);
232
233 const auto& motionEvent = static_cast<const MotionEvent&>(event);
234 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
235 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000236 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
237 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700240 });
Jackal Guof9696682018-10-05 12:23:23 +0800241 }
242
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700243 void assertFilterInputEventWasNotCalled() {
244 std::scoped_lock lock(mLock);
245 ASSERT_EQ(nullptr, mFilteredEvent);
246 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700249 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800250 ASSERT_TRUE(mConfigurationChangedTime)
251 << "Timed out waiting for configuration changed call";
252 ASSERT_EQ(*mConfigurationChangedTime, when);
253 mConfigurationChangedTime = std::nullopt;
254 }
255
256 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700257 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800258 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800259 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800260 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
261 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
262 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
263 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
264 mLastNotifySwitch = std::nullopt;
265 }
266
chaviwfd6d3512019-03-25 13:23:49 -0700267 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700268 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800269 ASSERT_EQ(touchedToken, mOnPointerDownToken);
270 mOnPointerDownToken.clear();
271 }
272
273 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700274 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800275 ASSERT_TRUE(mOnPointerDownToken == nullptr)
276 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700277 }
278
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700279 // This function must be called soon after the expected ANR timer starts,
280 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700282 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_NO_FATAL_FAILURE(
288 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700290 }
291
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000292 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800293 const sp<WindowInfoHandle>& window) {
294 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
295 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
296 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500297 }
298
Prabir Pradhanedd96402022-02-15 01:46:16 -0800299 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
300 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000301 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800302 std::unique_lock lock(mLock);
303 android::base::ScopedLockAssertion assumeLocked(mLock);
304 AnrResult result;
305 ASSERT_NO_FATAL_FAILURE(result =
306 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000307 ASSERT_EQ(expectedToken, result.token);
308 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500309 }
310
Prabir Pradhanedd96402022-02-15 01:46:16 -0800311 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000312 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500313 std::unique_lock lock(mLock);
314 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800315 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
316 const auto& [token, _] = result;
317 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000318 }
319
Prabir Pradhanedd96402022-02-15 01:46:16 -0800320 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000321 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800322 std::unique_lock lock(mLock);
323 android::base::ScopedLockAssertion assumeLocked(mLock);
324 AnrResult result;
325 ASSERT_NO_FATAL_FAILURE(
326 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000327 ASSERT_EQ(expectedToken, result.token);
328 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800329 }
330
331 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000332 sp<IBinder> getResponsiveWindowToken() {
333 std::unique_lock lock(mLock);
334 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800335 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
336 const auto& [token, _] = result;
337 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700338 }
339
340 void assertNotifyAnrWasNotCalled() {
341 std::scoped_lock lock(mLock);
342 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800343 ASSERT_TRUE(mAnrWindows.empty());
344 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500345 << "ANR was not called, but please also consume the 'connection is responsive' "
346 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700347 }
348
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000349 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800350 std::unique_lock lock(mLock);
351 base::ScopedLockAssertion assumeLocked(mLock);
352
353 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
354 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000355 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800356 enabled;
357 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000358 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
359 << ") to be called.";
360 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800361 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 auto request = *mPointerCaptureRequest;
363 mPointerCaptureRequest.reset();
364 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800365 }
366
367 void assertSetPointerCaptureNotCalled() {
368 std::unique_lock lock(mLock);
369 base::ScopedLockAssertion assumeLocked(mLock);
370
371 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000372 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800373 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
378
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700379 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
380 const sp<IBinder>& targetToken) {
381 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800382 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800383 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800384 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800386 }
387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800388 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
389 std::unique_lock lock(mLock);
390 base::ScopedLockAssertion assumeLocked(mLock);
391 std::optional<sp<IBinder>> receivedToken =
392 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
393 mNotifyInputChannelBroken);
394 ASSERT_TRUE(receivedToken.has_value());
395 ASSERT_EQ(token, *receivedToken);
396 }
397
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800398 /**
399 * Set policy timeout. A value of zero means next key will not be intercepted.
400 */
401 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
402 mInterceptKeyTimeout = timeout;
403 }
404
Josep del Riob3981622023-04-18 15:49:45 +0000405 void assertUserActivityPoked() {
406 std::scoped_lock lock(mLock);
407 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
408 }
409
410 void assertUserActivityNotPoked() {
411 std::scoped_lock lock(mLock);
412 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
413 }
414
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000415 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000416 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
417 }
418
419 void assertNotifyDeviceInteractionWasNotCalled() {
420 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
421 }
422
Michael Wrightd02c5b62014-02-10 15:10:22 -0800423private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700424 std::mutex mLock;
425 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
426 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
427 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
428 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800429
Prabir Pradhan99987712020-11-10 18:43:05 -0800430 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000431
432 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800433
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700434 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700435 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800436 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
437 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700438 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800439 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
440 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700441
arthurhungf452d0b2021-01-06 00:19:52 +0800442 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800443 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000444 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800445
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800446 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
447
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000448 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000449
Prabir Pradhanedd96402022-02-15 01:46:16 -0800450 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
451 // for a specific container to become non-empty. When the container is non-empty, return the
452 // first entry from the container and erase it.
453 template <class T>
454 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
455 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
456 // If there is an ANR, Dispatcher won't be idle because there are still events
457 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
458 // before checking if ANR was called.
459 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
460 // to provide it some time to act. 100ms seems reasonable.
461 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
462 const std::chrono::time_point start = std::chrono::steady_clock::now();
463 std::optional<T> token =
464 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
465 if (!token.has_value()) {
466 ADD_FAILURE() << "Did not receive the ANR callback";
467 return {};
468 }
469
470 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
471 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
472 // the dispatcher started counting before this function was called
473 if (std::chrono::abs(timeout - waited) > 100ms) {
474 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
475 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
476 << "ms, but waited "
477 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
478 << "ms instead";
479 }
480 return *token;
481 }
482
483 template <class T>
484 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
485 std::queue<T>& storage,
486 std::unique_lock<std::mutex>& lock,
487 std::condition_variable& condition)
488 REQUIRES(mLock) {
489 condition.wait_for(lock, timeout,
490 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
491 if (storage.empty()) {
492 ADD_FAILURE() << "Did not receive the expected callback";
493 return std::nullopt;
494 }
495 T item = storage.front();
496 storage.pop();
497 return std::make_optional(item);
498 }
499
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600500 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700501 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800502 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800503 }
504
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000505 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800506 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700507 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800508 ASSERT_TRUE(pid.has_value());
509 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700510 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500511 }
512
Prabir Pradhanedd96402022-02-15 01:46:16 -0800513 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000514 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500515 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800516 ASSERT_TRUE(pid.has_value());
517 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500518 mNotifyAnr.notify_all();
519 }
520
521 void notifyNoFocusedWindowAnr(
522 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
523 std::scoped_lock lock(mLock);
524 mAnrApplications.push(applicationHandle);
525 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800526 }
527
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800528 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
529 std::scoped_lock lock(mLock);
530 mBrokenInputChannels.push(connectionToken);
531 mNotifyInputChannelBroken.notify_all();
532 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800533
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600534 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700535
Chris Yef59a2f42020-10-16 12:55:26 -0700536 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
537 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
538 const std::vector<float>& values) override {}
539
540 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
541 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000542
Chris Yefb552902021-02-03 17:18:37 -0800543 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700546 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000547 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700548 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000549 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
550 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800551 break;
552 }
553
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700554 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000555 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
556 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800557 break;
558 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700559 default: {
560 ADD_FAILURE() << "Should only filter keys or motions";
561 break;
562 }
Jackal Guof9696682018-10-05 12:23:23 +0800563 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800564 return true;
565 }
566
Prabir Pradhana41d2442023-04-20 21:30:40 +0000567 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
568 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800569 // Clear intercept state when we handled the event.
570 mInterceptKeyTimeout = 0ms;
571 }
572 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600574 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575
Prabir Pradhana41d2442023-04-20 21:30:40 +0000576 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800577 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
578 // Clear intercept state so we could dispatch the event in next wake.
579 mInterceptKeyTimeout = 0ms;
580 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 }
582
Prabir Pradhana41d2442023-04-20 21:30:40 +0000583 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
584 uint32_t) override {
585 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800586 }
587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
589 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700590 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800591 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
592 * essentially a passthrough for notifySwitch.
593 */
Harry Cutts33476232023-01-30 19:57:29 +0000594 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800595 }
596
Josep del Riob3981622023-04-18 15:49:45 +0000597 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
598 std::scoped_lock lock(mLock);
599 mPokedUserActivity = true;
600 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800601
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600602 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700603 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700604 mOnPointerDownToken = newToken;
605 }
606
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000607 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800608 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000609 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800610 mPointerCaptureChangedCondition.notify_all();
611 }
612
arthurhungf452d0b2021-01-06 00:19:52 +0800613 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
614 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800615 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800616 mDropTargetWindowToken = token;
617 }
618
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000619 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000620 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000621 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
622 }
623
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700624 void assertFilterInputEventWasCalledInternal(
625 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700626 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800627 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700628 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800629 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800630 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800631};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700632} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634// --- InputDispatcherTest ---
635
636class InputDispatcherTest : public testing::Test {
637protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000641 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000642 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
643 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000644 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000645 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700646 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800647 }
648
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000649 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700650 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000651 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700652 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700654
655 /**
656 * Used for debugging when writing the test
657 */
658 void dumpDispatcherState() {
659 std::string dump;
660 mDispatcher->dump(dump);
661 std::stringstream ss(dump);
662 std::string to;
663
664 while (std::getline(ss, to, '\n')) {
665 ALOGE("%s", to.c_str());
666 }
667 }
Vishnu Nair958da932020-08-21 17:12:37 -0700668
Chavi Weingarten847e8512023-03-29 00:26:09 +0000669 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700670 FocusRequest request;
671 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000672 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700673 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
674 request.displayId = window->getInfo()->displayId;
675 mDispatcher->setFocusedWindow(request);
676 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677};
678
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
680 KeyEvent event;
681
682 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800683 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
684 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000685 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600686 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800687 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000688 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000689 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 << "Should reject key events with undefined action.";
691
692 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
694 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600695 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000697 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 << "Should reject key events with ACTION_MULTIPLE.";
700}
701
702TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
703 MotionEvent event;
704 PointerProperties pointerProperties[MAX_POINTERS + 1];
705 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800706 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800707 pointerProperties[i].clear();
708 pointerProperties[i].id = i;
709 pointerCoords[i].clear();
710 }
711
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800712 // Some constants commonly used below
713 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
714 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
715 constexpr int32_t metaState = AMETA_NONE;
716 constexpr MotionClassification classification = MotionClassification::NONE;
717
chaviw9eaa22c2020-07-01 16:21:27 -0700718 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800719 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700722 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700723 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
724 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000725 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800726 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000727 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000728 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800729 << "Should reject motion events with undefined action.";
730
731 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800732 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800733 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
734 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
735 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
736 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000737 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000739 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000740 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800741 << "Should reject motion events with pointer down index too large.";
742
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700744 AMOTION_EVENT_ACTION_POINTER_DOWN |
745 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700746 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
747 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700748 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with pointer down index too small.";
754
755 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800757 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
758 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
759 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
760 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with pointer up index too large.";
766
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700768 AMOTION_EVENT_ACTION_POINTER_UP |
769 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700770 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer up index too small.";
778
779 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
781 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
784 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with 0 pointers.";
790
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with more than MAX_POINTERS pointers.";
801
802 // Rejects motion events with invalid pointer ids.
803 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800804 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
805 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700806 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700807 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
808 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000809 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000811 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000812 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800813 << "Should reject motion events with pointer ids less than 0.";
814
815 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
826
827 // Rejects motion events with duplicate pointer ids.
828 pointerProperties[0].id = 1;
829 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800830 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
831 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700832 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700833 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
834 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000835 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000838 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800839 << "Should reject motion events with duplicate pointer ids.";
840}
841
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
843
844TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
845 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000846 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800847 ASSERT_TRUE(mDispatcher->waitForIdle());
848
849 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
850}
851
852TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000853 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
854 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000855 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800856
857 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
858 args.policyFlags |= POLICY_FLAG_TRUSTED;
859 mFakePolicy->assertNotifySwitchWasCalled(args);
860}
861
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700862namespace {
863
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700864static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700865// Default input dispatching timeout if there is no focused application or paused window
866// from which to determine an appropriate dispatching timeout.
867static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
868 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
869 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800870
871class FakeApplicationHandle : public InputApplicationHandle {
872public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 FakeApplicationHandle() {
874 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700875 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500876 mInfo.dispatchingTimeoutMillis =
877 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700878 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800879 virtual ~FakeApplicationHandle() {}
880
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000881 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700882
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500883 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
884 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800886};
887
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800888class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800889public:
Garfield Tan15601662020-09-22 15:32:38 -0700890 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800891 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700892 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800893 }
894
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700895 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700897 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700898 if (!consumeSeq) {
899 return nullptr;
900 }
901 finishEvent(*consumeSeq);
902 return event;
903 }
904
905 /**
906 * Receive an event without acknowledging it.
907 * Return the sequence number that could later be used to send finished signal.
908 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700909 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
910 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800911 uint32_t consumeSeq;
912 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800913
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800914 std::chrono::time_point start = std::chrono::steady_clock::now();
915 status_t status = WOULD_BLOCK;
916 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000917 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800918 &event);
919 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700920 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800921 break;
922 }
923 }
924
925 if (status == WOULD_BLOCK) {
926 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700927 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928 }
929
930 if (status != OK) {
931 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700932 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 }
934 if (event == nullptr) {
935 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700936 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 if (outEvent != nullptr) {
939 *outEvent = event;
940 }
941 return consumeSeq;
942 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 /**
945 * To be used together with "receiveEvent" to complete the consumption of an event.
946 */
947 void finishEvent(uint32_t consumeSeq) {
948 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
949 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800950 }
951
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000952 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
953 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
954 ASSERT_EQ(OK, status);
955 }
956
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700957 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000958 std::optional<int32_t> expectedDisplayId,
959 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700960 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800961
962 ASSERT_NE(nullptr, event) << mName.c_str()
963 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800964 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
966 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800967
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000968 if (expectedDisplayId.has_value()) {
969 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
970 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800971
Tiger Huang8664f8c2018-10-11 19:14:35 +0800972 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800974 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700975 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976 if (expectedFlags.has_value()) {
977 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
978 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979 break;
980 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800982 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700983 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000984 if (expectedFlags.has_value()) {
985 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
986 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987 break;
988 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100990 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
991 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700992 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800993 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
994 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700995 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000996 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
997 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800999 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1000 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001001 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001002 }
1003
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001004 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001005 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001006
1007 if (event == nullptr) {
1008 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1009 return nullptr;
1010 }
1011
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 if (event->getType() != InputEventType::MOTION) {
1013 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001014 return nullptr;
1015 }
1016 return static_cast<MotionEvent*>(event);
1017 }
1018
1019 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1020 MotionEvent* motionEvent = consumeMotion();
1021 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1022 ASSERT_THAT(*motionEvent, matcher);
1023 }
1024
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001025 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001026 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001027 ASSERT_NE(nullptr, event) << mName.c_str()
1028 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001029 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1030 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001031
1032 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1033 << mName.c_str() << ": event displayId should always be NONE.";
1034
1035 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1036 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001037 }
1038
Prabir Pradhan99987712020-11-10 18:43:05 -08001039 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001040 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001041 ASSERT_NE(nullptr, event) << mName.c_str()
1042 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1044 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001045
1046 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1047 << mName.c_str() << ": event displayId should always be NONE.";
1048
1049 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1050 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1051 }
1052
arthurhungb89ccb02020-12-30 16:19:01 +08001053 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001054 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001055 ASSERT_NE(nullptr, event) << mName.c_str()
1056 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001057 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001058
1059 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1060 << mName.c_str() << ": event displayId should always be NONE.";
1061
1062 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1063 EXPECT_EQ(isExiting, dragEvent.isExiting());
1064 EXPECT_EQ(x, dragEvent.getX());
1065 EXPECT_EQ(y, dragEvent.getY());
1066 }
1067
Antonio Kantekf16f2832021-09-28 04:39:20 +00001068 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001069 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 ASSERT_NE(nullptr, event) << mName.c_str()
1071 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001072 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1073 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001074
1075 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1076 << mName.c_str() << ": event displayId should always be NONE.";
1077 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1078 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1079 }
1080
chaviwd1c23182019-12-20 18:44:56 -08001081 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001082 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001083 if (event == nullptr) {
1084 return;
1085 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001086 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001087 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1088 ADD_FAILURE() << "Received key event "
1089 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001090 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001091 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1092 ADD_FAILURE() << "Received motion event "
1093 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001094 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1096 ADD_FAILURE() << "Received focus event, hasFocus = "
1097 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001098 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001099 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1100 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1101 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001102 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001103 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1104 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1105 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001106 }
1107 FAIL() << mName.c_str()
1108 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001109 }
1110
1111 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1112
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001113 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1114
chaviwd1c23182019-12-20 18:44:56 -08001115protected:
1116 std::unique_ptr<InputConsumer> mConsumer;
1117 PreallocatedInputEventFactory mEventFactory;
1118
1119 std::string mName;
1120};
1121
chaviw3277faf2021-05-19 16:45:23 -05001122class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001123public:
1124 static const int32_t WIDTH = 600;
1125 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001126
Chris Yea209fde2020-07-22 13:54:51 -07001127 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001128 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001130 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001131 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001132 base::Result<std::unique_ptr<InputChannel>> channel =
1133 dispatcher->createInputChannel(name);
1134 token = (*channel)->getConnectionToken();
1135 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001136 }
1137
1138 inputApplicationHandle->updateInfo();
1139 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1140
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001141 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001142 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001143 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001145 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001146 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001147 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001148 mInfo.globalScaleFactor = 1.0;
1149 mInfo.touchableRegion.clear();
1150 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001151 mInfo.ownerPid = WINDOW_PID;
1152 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001153 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001154 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001155 }
1156
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001157 sp<FakeWindowHandle> clone(int32_t displayId) {
1158 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1159 handle->mInfo = mInfo;
1160 handle->mInfo.displayId = displayId;
1161 handle->mInfo.id = sId++;
1162 handle->mInputReceiver = mInputReceiver;
1163 return handle;
1164 }
1165
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001166 void setTouchable(bool touchable) {
1167 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1168 }
chaviwd1c23182019-12-20 18:44:56 -08001169
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 void setFocusable(bool focusable) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1172 }
1173
1174 void setVisible(bool visible) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1176 }
Vishnu Nair958da932020-08-21 17:12:37 -07001177
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001178 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001179 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001180 }
1181
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001182 void setPaused(bool paused) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1184 }
1185
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001186 void setPreventSplitting(bool preventSplitting) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001188 }
1189
1190 void setSlippery(bool slippery) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1192 }
1193
1194 void setWatchOutsideTouch(bool watchOutside) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1196 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001197
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001198 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1199
1200 void setInterceptsStylus(bool interceptsStylus) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1202 }
1203
1204 void setDropInput(bool dropInput) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1206 }
1207
1208 void setDropInputIfObscured(bool dropInputIfObscured) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1210 }
1211
1212 void setNoInputChannel(bool noInputChannel) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1214 }
1215
Josep del Riob3981622023-04-18 15:49:45 +00001216 void setDisableUserActivity(bool disableUserActivity) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1218 }
1219
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001220 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1221
chaviw3277faf2021-05-19 16:45:23 -05001222 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001223
Bernardo Rufino7393d172021-02-26 13:56:11 +00001224 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1225
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001226 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001227 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001228 mInfo.touchableRegion.clear();
1229 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001230
1231 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1232 ui::Transform translate;
1233 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1234 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001235 }
1236
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001237 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1238
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001239 void setIsWallpaper(bool isWallpaper) {
1240 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1241 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001242
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001243 void setDupTouchToWallpaper(bool hasWallpaper) {
1244 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1245 }
chaviwd1c23182019-12-20 18:44:56 -08001246
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001247 void setTrustedOverlay(bool trustedOverlay) {
1248 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1249 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001250
chaviw9eaa22c2020-07-01 16:21:27 -07001251 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1252 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1253 }
1254
1255 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001256
yunho.shinf4a80b82020-11-16 21:13:57 +09001257 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1258
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001259 KeyEvent* consumeKey() {
1260 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1261 if (event == nullptr) {
1262 ADD_FAILURE() << "Consume failed : no event";
1263 return nullptr;
1264 }
1265 if (event->getType() != InputEventType::KEY) {
1266 ADD_FAILURE() << "Instead of key event, got " << *event;
1267 return nullptr;
1268 }
1269 return static_cast<KeyEvent*>(event);
1270 }
1271
1272 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1273 KeyEvent* keyEvent = consumeKey();
1274 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1275 ASSERT_THAT(*keyEvent, matcher);
1276 }
1277
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001278 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 }
1281
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001282 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001283 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001284 }
1285
Svet Ganov5d3bc372020-01-26 23:11:07 -08001286 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001287 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001288 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1289 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001290 }
1291
1292 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001294 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1295 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001296 }
1297
1298 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001299 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001300 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1301 }
1302
1303 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1304 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001305 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001306 expectedFlags);
1307 }
1308
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001310 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1311 int32_t expectedFlags = 0) {
1312 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1313 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001314 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001315 }
1316
1317 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001318 int32_t expectedFlags = 0) {
1319 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1320 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001321 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001322 }
1323
1324 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001325 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001327 expectedFlags);
1328 }
1329
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001330 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1331 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001332 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001333 expectedFlags);
1334 }
1335
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001336 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1337 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001338 MotionEvent* motionEvent = consumeMotion();
1339 ASSERT_NE(nullptr, motionEvent);
1340 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1341 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1342 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001343 }
1344
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001345 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1346 ASSERT_NE(mInputReceiver, nullptr)
1347 << "Cannot consume events from a window with no receiver";
1348 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1349 }
1350
Prabir Pradhan99987712020-11-10 18:43:05 -08001351 void consumeCaptureEvent(bool hasCapture) {
1352 ASSERT_NE(mInputReceiver, nullptr)
1353 << "Cannot consume events from a window with no receiver";
1354 mInputReceiver->consumeCaptureEvent(hasCapture);
1355 }
1356
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001357 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1358 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001359 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001360 ASSERT_THAT(*motionEvent, matcher);
1361 }
1362
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001363 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001364 std::optional<int32_t> expectedDisplayId,
1365 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001366 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1367 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1368 expectedFlags);
1369 }
1370
arthurhungb89ccb02020-12-30 16:19:01 +08001371 void consumeDragEvent(bool isExiting, float x, float y) {
1372 mInputReceiver->consumeDragEvent(isExiting, x, y);
1373 }
1374
Antonio Kantekf16f2832021-09-28 04:39:20 +00001375 void consumeTouchModeEvent(bool inTouchMode) {
1376 ASSERT_NE(mInputReceiver, nullptr)
1377 << "Cannot consume events from a window with no receiver";
1378 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1379 }
1380
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001381 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001382 if (mInputReceiver == nullptr) {
1383 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1384 return std::nullopt;
1385 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001386 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001387 }
1388
1389 void finishEvent(uint32_t sequenceNum) {
1390 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1391 mInputReceiver->finishEvent(sequenceNum);
1392 }
1393
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001394 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1395 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1396 mInputReceiver->sendTimeline(inputEventId, timeline);
1397 }
1398
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001399 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001400 if (mInputReceiver == nullptr) {
1401 return nullptr;
1402 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001403 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001404 }
1405
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001406 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001407 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001408 if (event == nullptr) {
1409 ADD_FAILURE() << "Consume failed : no event";
1410 return nullptr;
1411 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001412 if (event->getType() != InputEventType::MOTION) {
1413 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001414 return nullptr;
1415 }
1416 return static_cast<MotionEvent*>(event);
1417 }
1418
Arthur Hungb92218b2018-08-14 12:00:21 +08001419 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001420 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001421 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001422 return; // Can't receive events if the window does not have input channel
1423 }
1424 ASSERT_NE(nullptr, mInputReceiver)
1425 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001426 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001427 }
1428
chaviwaf87b3e2019-10-01 16:59:28 -07001429 sp<IBinder> getToken() { return mInfo.token; }
1430
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001431 const std::string& getName() { return mName; }
1432
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001433 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001434 mInfo.ownerPid = ownerPid;
1435 mInfo.ownerUid = ownerUid;
1436 }
1437
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001438 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001439
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001440 void destroyReceiver() { mInputReceiver = nullptr; }
1441
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001442 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1443
chaviwd1c23182019-12-20 18:44:56 -08001444private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001445 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001446 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001447 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001448 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001449 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001450};
1451
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001452std::atomic<int32_t> FakeWindowHandle::sId{1};
1453
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001454class FakeMonitorReceiver {
1455public:
1456 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
1457 int32_t displayId) {
1458 base::Result<std::unique_ptr<InputChannel>> channel =
1459 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
1460 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1461 }
1462
1463 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1464
1465 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1466 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1467 expectedFlags);
1468 }
1469
1470 std::optional<int32_t> receiveEvent() {
1471 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1472 }
1473
1474 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1475
1476 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1477 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1478 expectedDisplayId, expectedFlags);
1479 }
1480
1481 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1482 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1483 expectedDisplayId, expectedFlags);
1484 }
1485
1486 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1487 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1488 expectedDisplayId, expectedFlags);
1489 }
1490
1491 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1492 mInputReceiver->consumeMotionEvent(
1493 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1494 WithDisplayId(expectedDisplayId),
1495 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1496 }
1497
1498 void consumeMotionPointerDown(int32_t pointerIdx) {
1499 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1500 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1501 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1502 /*expectedFlags=*/0);
1503 }
1504
1505 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1506 mInputReceiver->consumeMotionEvent(matcher);
1507 }
1508
1509 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1510
1511 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1512
1513private:
1514 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1515};
1516
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001517static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519 int32_t displayId = ADISPLAY_ID_NONE,
1520 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001521 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001522 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001523 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001524 KeyEvent event;
1525 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1526
1527 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001528 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001529 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1530 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001531
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001532 if (!allowKeyRepeat) {
1533 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1534 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001535 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001536 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001537}
1538
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001539static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1540 InputEventInjectionResult result =
1541 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1542 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1543 if (result != InputEventInjectionResult::TIMED_OUT) {
1544 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1545 }
1546}
1547
1548static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001549 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001550 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001551}
1552
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001553// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1554// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1555// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001556static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1557 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001558 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001559 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001560 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001561}
1562
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001563static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001564 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001565 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001566}
1567
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001568static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001569 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001570 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001571 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001572 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001573 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1574 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001575}
1576
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001577static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001578 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1579 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001580 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001581 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1582 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001583 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001584 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001585 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001586 MotionEventBuilder motionBuilder =
1587 MotionEventBuilder(action, source)
1588 .displayId(displayId)
1589 .eventTime(eventTime)
1590 .rawXCursorPosition(cursorPosition.x)
1591 .rawYCursorPosition(cursorPosition.y)
1592 .pointer(
1593 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1594 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1595 motionBuilder.downTime(eventTime);
1596 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001597
1598 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001599 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1600 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001601}
1602
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001603static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1604 int32_t displayId,
1605 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001606 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001607}
1608
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001609static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1610 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001611 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001612 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001613}
1614
Jackal Guof9696682018-10-05 12:23:23 +08001615static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1616 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1617 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001618 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001619 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1620 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001621
1622 return args;
1623}
1624
Josep del Riob3981622023-04-18 15:49:45 +00001625static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1626 int32_t displayId = ADISPLAY_ID_NONE) {
1627 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1628 // Define a valid key event.
1629 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001630 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001631 currentTime);
1632
1633 return args;
1634}
1635
1636static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1637 int32_t displayId = ADISPLAY_ID_NONE) {
1638 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1639 // Define a valid key event.
1640 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001641 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001642 AMETA_NONE, currentTime);
1643
1644 return args;
1645}
1646
Prabir Pradhan678438e2023-04-13 19:32:51 +00001647[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1648 int32_t displayId,
1649 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001650 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001651 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1652 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1653 }
1654
chaviwd1c23182019-12-20 18:44:56 -08001655 PointerProperties pointerProperties[pointerCount];
1656 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001657
chaviwd1c23182019-12-20 18:44:56 -08001658 for (size_t i = 0; i < pointerCount; i++) {
1659 pointerProperties[i].clear();
1660 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001661 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001662
chaviwd1c23182019-12-20 18:44:56 -08001663 pointerCoords[i].clear();
1664 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1665 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1666 }
Jackal Guof9696682018-10-05 12:23:23 +08001667
1668 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1669 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001670 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001671 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1672 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001673 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001674 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001675 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001676 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001677
1678 return args;
1679}
1680
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001681static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1682 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1683}
1684
chaviwd1c23182019-12-20 18:44:56 -08001685static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1686 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1687}
1688
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001689static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1690 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001691 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001692}
1693
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001694} // namespace
1695
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001696/**
1697 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1698 * broken channel.
1699 */
1700TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1702 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001703 sp<FakeWindowHandle>::make(application, mDispatcher,
1704 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001705
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001706 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001707
1708 // Window closes its channel, but the window remains.
1709 window->destroyReceiver();
1710 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1711}
1712
Arthur Hungb92218b2018-08-14 12:00:21 +08001713TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001714 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001715 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1716 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001722
1723 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001724 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001725}
1726
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001727TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001729 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1730 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001731
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001732 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001733 // Inject a MotionEvent to an unknown display.
1734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001735 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1737
1738 // Window should receive motion event.
1739 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1740}
1741
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001742/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001743 * Calling onWindowInfosChanged once should not cause any issues.
1744 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001745 * called twice.
1746 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001747TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1750 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001751 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001752
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001755 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001756 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001757 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001758
1759 // Window should receive motion event.
1760 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1761}
1762
1763/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001764 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001765 */
1766TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001768 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1769 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001770 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001771
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001772 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1773 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001776 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001778
1779 // Window should receive motion event.
1780 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1781}
1782
Arthur Hungb92218b2018-08-14 12:00:21 +08001783// The foreground window should receive the first touch down event.
1784TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001786 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001787 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001788 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001789 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001790
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged(
1792 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001794 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001796
1797 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001798 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001799 windowSecond->assertNoEvents();
1800}
1801
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001802/**
1803 * Two windows: A top window, and a wallpaper behind the window.
1804 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1805 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001806 * 1. foregroundWindow <-- dup touch to wallpaper
1807 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001808 */
1809TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1811 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001812 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001813 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001814 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001815 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001816 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001817
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001818 mDispatcher->onWindowInfosChanged(
1819 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001821 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001822 {100, 200}))
1823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1824
1825 // Both foreground window and its wallpaper should receive the touch down
1826 foregroundWindow->consumeMotionDown();
1827 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1828
1829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001830 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001831 ADISPLAY_ID_DEFAULT, {110, 200}))
1832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1833
1834 foregroundWindow->consumeMotionMove();
1835 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1836
1837 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001838 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001839 foregroundWindow->consumeMotionCancel();
1840 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1841 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1842}
1843
1844/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001845 * Two fingers down on the window, and lift off the first finger.
1846 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1847 * contains a single pointer.
1848 */
1849TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1851 sp<FakeWindowHandle> window =
1852 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001854 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001855 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1857 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1858 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001859 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001860 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1861 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1862 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1863 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001864 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001865 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1866 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1867 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1868 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001869 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1870 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1871 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1872
1873 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001874 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001875 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1876 window->consumeMotionEvent(
1877 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1878}
1879
1880/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001881 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1882 * with the following differences:
1883 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1884 * clean up the connection.
1885 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1886 * Ensure that there's no crash in the dispatcher.
1887 */
1888TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1890 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001891 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001892 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001893 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001894 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001895 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001896
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001897 mDispatcher->onWindowInfosChanged(
1898 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001900 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001901 {100, 200}))
1902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1903
1904 // Both foreground window and its wallpaper should receive the touch down
1905 foregroundWindow->consumeMotionDown();
1906 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1907
1908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001909 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001910 ADISPLAY_ID_DEFAULT, {110, 200}))
1911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1912
1913 foregroundWindow->consumeMotionMove();
1914 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1915
1916 // Wallpaper closes its channel, but the window remains.
1917 wallpaperWindow->destroyReceiver();
1918 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1919
1920 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1921 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001922 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001923 foregroundWindow->consumeMotionCancel();
1924}
1925
Arthur Hungc539dbb2022-12-08 07:45:36 +00001926class ShouldSplitTouchFixture : public InputDispatcherTest,
1927 public ::testing::WithParamInterface<bool> {};
1928INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1929 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001930/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001931 * A single window that receives touch (on top), and a wallpaper window underneath it.
1932 * The top window gets a multitouch gesture.
1933 * Ensure that wallpaper gets the same gesture.
1934 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001935TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001937 sp<FakeWindowHandle> foregroundWindow =
1938 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1939 foregroundWindow->setDupTouchToWallpaper(true);
1940 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941
1942 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001943 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001944 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001945
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001946 mDispatcher->onWindowInfosChanged(
1947 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948
1949 // Touch down on top window
1950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001951 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952 {100, 100}))
1953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1954
1955 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001956 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001957 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1958
1959 // Second finger down on the top window
1960 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001961 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001963 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1964 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 .build();
1966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001967 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968 InputEventInjectionSync::WAIT_FOR_RESULT))
1969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1970
Harry Cutts33476232023-01-30 19:57:29 +00001971 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1972 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001973 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001974
1975 const MotionEvent secondFingerUpEvent =
1976 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1977 .displayId(ADISPLAY_ID_DEFAULT)
1978 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001979 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1980 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001981 .build();
1982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001983 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001984 InputEventInjectionSync::WAIT_FOR_RESULT))
1985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1986 foregroundWindow->consumeMotionPointerUp(0);
1987 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1988
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001990 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001991 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1992 AINPUT_SOURCE_TOUCHSCREEN)
1993 .displayId(ADISPLAY_ID_DEFAULT)
1994 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001995 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001996 .x(100)
1997 .y(100))
1998 .build(),
1999 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2001 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2002 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003}
2004
2005/**
2006 * Two windows: a window on the left and window on the right.
2007 * A third window, wallpaper, is behind both windows, and spans both top windows.
2008 * The first touch down goes to the left window. A second pointer touches down on the right window.
2009 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2010 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2011 * ACTION_POINTER_DOWN(1).
2012 */
2013TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2014 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2015 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002016 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002018 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002019
2020 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002021 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002022 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002023 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002024
2025 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002026 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002028 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002029
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002030 mDispatcher->onWindowInfosChanged(
2031 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2032 {},
2033 0,
2034 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035
2036 // Touch down on left window
2037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002039 {100, 100}))
2040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2041
2042 // Both foreground window and its wallpaper should receive the touch down
2043 leftWindow->consumeMotionDown();
2044 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2045
2046 // Second finger down on the right window
2047 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002048 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002050 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2051 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002052 .build();
2053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002054 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002055 InputEventInjectionSync::WAIT_FOR_RESULT))
2056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2057
2058 leftWindow->consumeMotionMove();
2059 // Since the touch is split, right window gets ACTION_DOWN
2060 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002061 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002062 expectedWallpaperFlags);
2063
2064 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002065 mDispatcher->onWindowInfosChanged(
2066 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002067 leftWindow->consumeMotionCancel();
2068 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2069 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2070
2071 // The pointer that's still down on the right window moves, and goes to the right window only.
2072 // As far as the dispatcher's concerned though, both pointers are still present.
2073 const MotionEvent secondFingerMoveEvent =
2074 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2075 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002076 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2077 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078 .build();
2079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002080 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002081 InputEventInjectionSync::WAIT_FOR_RESULT));
2082 rightWindow->consumeMotionMove();
2083
2084 leftWindow->assertNoEvents();
2085 rightWindow->assertNoEvents();
2086 wallpaperWindow->assertNoEvents();
2087}
2088
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089/**
2090 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2091 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2092 * The right window should receive ACTION_DOWN.
2093 */
2094TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002096 sp<FakeWindowHandle> leftWindow =
2097 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2098 leftWindow->setFrame(Rect(0, 0, 200, 200));
2099 leftWindow->setDupTouchToWallpaper(true);
2100 leftWindow->setSlippery(true);
2101
2102 sp<FakeWindowHandle> rightWindow =
2103 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2104 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002105
2106 sp<FakeWindowHandle> wallpaperWindow =
2107 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2108 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002110 mDispatcher->onWindowInfosChanged(
2111 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2112 {},
2113 0,
2114 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002115
Arthur Hungc539dbb2022-12-08 07:45:36 +00002116 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002119 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002121
2122 // Both foreground window and its wallpaper should receive the touch down
2123 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002124 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2125
Arthur Hungc539dbb2022-12-08 07:45:36 +00002126 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002128 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002129 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2131
Arthur Hungc539dbb2022-12-08 07:45:36 +00002132 leftWindow->consumeMotionCancel();
2133 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2134 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002135}
2136
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002137/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002138 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2139 * interactive, it might stop sending this flag.
2140 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2141 * to have a consistent input stream.
2142 *
2143 * Test procedure:
2144 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2145 * DOWN (new gesture).
2146 *
2147 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2148 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2149 *
2150 * We technically just need a single window here, but we are using two windows (spy on top and a
2151 * regular window below) to emulate the actual situation where it happens on the device.
2152 */
2153TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2155 sp<FakeWindowHandle> spyWindow =
2156 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2157 spyWindow->setFrame(Rect(0, 0, 200, 200));
2158 spyWindow->setTrustedOverlay(true);
2159 spyWindow->setSpy(true);
2160
2161 sp<FakeWindowHandle> window =
2162 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2163 window->setFrame(Rect(0, 0, 200, 200));
2164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002165 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002166 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002167
2168 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002169 mDispatcher->notifyMotion(
2170 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2171 .deviceId(touchDeviceId)
2172 .policyFlags(DEFAULT_POLICY_FLAGS)
2173 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2174 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002175
Prabir Pradhan678438e2023-04-13 19:32:51 +00002176 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2177 .deviceId(touchDeviceId)
2178 .policyFlags(DEFAULT_POLICY_FLAGS)
2179 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2180 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2181 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002182 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2183 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2184 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2185 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2186
2187 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002188 mDispatcher->notifyMotion(
2189 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2190 .deviceId(touchDeviceId)
2191 .policyFlags(0)
2192 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2193 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2194 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002195 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2196 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2197
2198 // We don't need to reset the device to reproduce the issue, but the reset event typically
2199 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002200 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002201
2202 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002203 mDispatcher->notifyMotion(
2204 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2205 .deviceId(touchDeviceId)
2206 .policyFlags(DEFAULT_POLICY_FLAGS)
2207 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2208 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002209 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2210 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2211
2212 // No more events
2213 spyWindow->assertNoEvents();
2214 window->assertNoEvents();
2215}
2216
2217/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002218 * Two windows: a window on the left and a window on the right.
2219 * Mouse is hovered from the right window into the left window.
2220 * Next, we tap on the left window, where the cursor was last seen.
2221 * The second tap is done onto the right window.
2222 * The mouse and tap are from two different devices.
2223 * We technically don't need to set the downtime / eventtime for these events, but setting these
2224 * explicitly helps during debugging.
2225 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2226 * In the buggy implementation, a tap on the right window would cause a crash.
2227 */
2228TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2230 sp<FakeWindowHandle> leftWindow =
2231 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2232 leftWindow->setFrame(Rect(0, 0, 200, 200));
2233
2234 sp<FakeWindowHandle> rightWindow =
2235 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2236 rightWindow->setFrame(Rect(200, 0, 400, 200));
2237
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002238 mDispatcher->onWindowInfosChanged(
2239 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2241 // stale.
2242 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2243 const int32_t mouseDeviceId = 6;
2244 const int32_t touchDeviceId = 4;
2245 // Move the cursor from right
2246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2249 AINPUT_SOURCE_MOUSE)
2250 .deviceId(mouseDeviceId)
2251 .downTime(baseTime + 10)
2252 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002254 .build()));
2255 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2256
2257 // .. to the left window
2258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002259 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002260 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2261 AINPUT_SOURCE_MOUSE)
2262 .deviceId(mouseDeviceId)
2263 .downTime(baseTime + 10)
2264 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002265 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002266 .build()));
2267 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2268 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2269 // Now tap the left window
2270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002271 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002272 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2273 AINPUT_SOURCE_TOUCHSCREEN)
2274 .deviceId(touchDeviceId)
2275 .downTime(baseTime + 40)
2276 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002277 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002278 .build()));
2279 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2280 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2281
2282 // release tap
2283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002284 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002285 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2286 AINPUT_SOURCE_TOUCHSCREEN)
2287 .deviceId(touchDeviceId)
2288 .downTime(baseTime + 40)
2289 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002290 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002291 .build()));
2292 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2293
2294 // Tap the window on the right
2295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002296 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002297 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2298 AINPUT_SOURCE_TOUCHSCREEN)
2299 .deviceId(touchDeviceId)
2300 .downTime(baseTime + 60)
2301 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002302 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002303 .build()));
2304 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2305
2306 // release tap
2307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002309 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2310 AINPUT_SOURCE_TOUCHSCREEN)
2311 .deviceId(touchDeviceId)
2312 .downTime(baseTime + 60)
2313 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002314 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002315 .build()));
2316 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2317
2318 // No more events
2319 leftWindow->assertNoEvents();
2320 rightWindow->assertNoEvents();
2321}
2322
2323/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002324 * Start hovering in a window. While this hover is still active, make another window appear on top.
2325 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2326 * While the top window is present, the hovering is stopped.
2327 * Later, hovering gets resumed again.
2328 * Ensure that new hover gesture is handled correctly.
2329 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2330 * to the window that's currently being hovered over.
2331 */
2332TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2334 sp<FakeWindowHandle> window =
2335 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2336 window->setFrame(Rect(0, 0, 200, 200));
2337
2338 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002339 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002340
2341 // Start hovering in the window
2342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2343 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2344 .build());
2345 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2346
2347 // Now, an obscuring window appears!
2348 sp<FakeWindowHandle> obscuringWindow =
2349 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2350 ADISPLAY_ID_DEFAULT,
2351 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2352 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2353 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2354 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2355 obscuringWindow->setNoInputChannel(true);
2356 obscuringWindow->setFocusable(false);
2357 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002358 mDispatcher->onWindowInfosChanged(
2359 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002360
2361 // While this new obscuring window is present, the hovering is stopped
2362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2363 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2364 .build());
2365 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2366
2367 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002369
2370 // And a new hover gesture starts.
2371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2372 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2373 .build());
2374 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2375}
2376
2377/**
2378 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2379 * the obscuring window.
2380 */
2381TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2383 sp<FakeWindowHandle> window =
2384 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2385 window->setFrame(Rect(0, 0, 200, 200));
2386
2387 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002388 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002389
2390 // Start hovering in the window
2391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2392 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2393 .build());
2394 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2395
2396 // Now, an obscuring window appears!
2397 sp<FakeWindowHandle> obscuringWindow =
2398 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2399 ADISPLAY_ID_DEFAULT,
2400 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2401 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2402 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2403 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2404 obscuringWindow->setNoInputChannel(true);
2405 obscuringWindow->setFocusable(false);
2406 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002407 mDispatcher->onWindowInfosChanged(
2408 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002409
2410 // While this new obscuring window is present, the hovering continues. The event can't go to the
2411 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2413 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2414 .build());
2415 obscuringWindow->assertNoEvents();
2416 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2417
2418 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002419 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002420
2421 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2422 // so it should generate a HOVER_ENTER
2423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2424 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2425 .build());
2426 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2427
2428 // Now the MOVE should be getting dispatched normally
2429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2430 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2431 .build());
2432 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2433}
2434
2435/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002436 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2437 * events are delivered to the window.
2438 */
2439TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2441 sp<FakeWindowHandle> window =
2442 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2443 window->setFrame(Rect(0, 0, 200, 200));
2444 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2445
2446 // Start hovering in the window
2447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2449 .build());
2450 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2451
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2453 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2456
2457 // Scroll with the mouse
2458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2459 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2460 .build());
2461 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2462}
2463
2464using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2465
2466/**
2467 * One window. Stylus down on the window. Next, touch from another device goes down.
2468 */
2469TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2471 sp<FakeWindowHandle> window =
2472 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2473 window->setFrame(Rect(0, 0, 200, 200));
2474
2475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2476
2477 constexpr int32_t touchDeviceId = 4;
2478 constexpr int32_t stylusDeviceId = 2;
2479
2480 // Stylus down
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2482 .deviceId(stylusDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2486
2487 // Touch down
2488 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
2490 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2491 .build());
2492 // Touch cancels stylus
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2494 WithCoords(100, 110)));
2495 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2496 WithCoords(140, 145)));
2497
2498 // Touch move
2499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2500 .deviceId(touchDeviceId)
2501 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2502 .build());
2503 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2504 WithCoords(141, 146)));
2505
2506 // Subsequent stylus movements are dropped
2507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2508 .deviceId(stylusDeviceId)
2509 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2510 .build());
2511 window->assertNoEvents();
2512}
2513
2514/**
2515 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2516 * down.
2517 * Similar test as above, but with added SPY window.
2518 */
2519TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2521 sp<FakeWindowHandle> window =
2522 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2523 sp<FakeWindowHandle> spyWindow =
2524 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2525 spyWindow->setFrame(Rect(0, 0, 200, 200));
2526 spyWindow->setTrustedOverlay(true);
2527 spyWindow->setSpy(true);
2528 window->setFrame(Rect(0, 0, 200, 200));
2529
2530 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2531
2532 constexpr int32_t touchDeviceId = 4;
2533 constexpr int32_t stylusDeviceId = 2;
2534
2535 // Stylus down
2536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2537 .deviceId(stylusDeviceId)
2538 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2539 .build());
2540 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2541 spyWindow->consumeMotionEvent(
2542 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2543
2544 // Touch down
2545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2546 .deviceId(touchDeviceId)
2547 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2548 .build());
2549
2550 // Touch move
2551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2552 .deviceId(touchDeviceId)
2553 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2554 .build());
2555 window->consumeMotionEvent(
2556 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2557 spyWindow->consumeMotionEvent(
2558 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2559 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2560 spyWindow->consumeMotionEvent(
2561 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2562 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2563 spyWindow->consumeMotionEvent(
2564 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2565 // Subsequent stylus movements are dropped
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2567 .deviceId(stylusDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2569 .build());
2570
2571 window->assertNoEvents();
2572 spyWindow->assertNoEvents();
2573}
2574
2575/**
2576 * One window. Stylus hover on the window. Next, touch from another device goes down.
2577 */
2578TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2580 sp<FakeWindowHandle> window =
2581 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2582 window->setFrame(Rect(0, 0, 200, 200));
2583
2584 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2585
2586 constexpr int32_t touchDeviceId = 4;
2587 constexpr int32_t stylusDeviceId = 2;
2588
2589 // Stylus down on the window
2590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2591 .deviceId(stylusDeviceId)
2592 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2593 .build());
2594 window->consumeMotionEvent(
2595 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2596
2597 // Touch down on window
2598 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2599 .deviceId(touchDeviceId)
2600 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2601 .build());
2602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2603 .deviceId(touchDeviceId)
2604 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2605 .build());
2606 window->consumeMotionEvent(
2607 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2608 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2609 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2610 // Subsequent stylus movements are ignored
2611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2612 .deviceId(stylusDeviceId)
2613 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2614 .build());
2615 window->assertNoEvents();
2616}
2617
2618/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002619 * Two windows: a window on the left and a window on the right.
2620 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2621 * down. Then, on the left window, also place second touch pointer down.
2622 * This test tries to reproduce a crash.
2623 * In the buggy implementation, second pointer down on the left window would cause a crash.
2624 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002625TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2627 sp<FakeWindowHandle> leftWindow =
2628 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2629 leftWindow->setFrame(Rect(0, 0, 200, 200));
2630
2631 sp<FakeWindowHandle> rightWindow =
2632 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2633 rightWindow->setFrame(Rect(200, 0, 400, 200));
2634
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002635 mDispatcher->onWindowInfosChanged(
2636 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002637
2638 const int32_t touchDeviceId = 4;
2639 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002640
2641 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2643 .deviceId(mouseDeviceId)
2644 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2645 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002646 leftWindow->consumeMotionEvent(
2647 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2648
2649 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2651 .deviceId(mouseDeviceId)
2652 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2653 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2654 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002655
2656 leftWindow->consumeMotionEvent(
2657 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2658 leftWindow->consumeMotionEvent(
2659 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2660
Prabir Pradhan678438e2023-04-13 19:32:51 +00002661 mDispatcher->notifyMotion(
2662 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2663 .deviceId(mouseDeviceId)
2664 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2665 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002668 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2669
2670 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2672 .deviceId(touchDeviceId)
2673 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2674 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002675 leftWindow->consumeMotionEvent(
2676 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002677 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2678
2679 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002680 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2681 .deviceId(touchDeviceId)
2682 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2683 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2684 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002685 leftWindow->consumeMotionEvent(
2686 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2687 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2688 // current implementation.
2689 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2690 rightWindow->consumeMotionEvent(
2691 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2692
2693 leftWindow->assertNoEvents();
2694 rightWindow->assertNoEvents();
2695}
2696
2697/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002698 * Two windows: a window on the left and a window on the right.
2699 * Mouse is hovered on the left window and stylus is hovered on the right window.
2700 */
2701TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2703 sp<FakeWindowHandle> leftWindow =
2704 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2705 leftWindow->setFrame(Rect(0, 0, 200, 200));
2706
2707 sp<FakeWindowHandle> rightWindow =
2708 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2709 rightWindow->setFrame(Rect(200, 0, 400, 200));
2710
2711 mDispatcher->onWindowInfosChanged(
2712 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2713
2714 const int32_t stylusDeviceId = 3;
2715 const int32_t mouseDeviceId = 6;
2716
2717 // Start hovering over the left window
2718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2719 .deviceId(mouseDeviceId)
2720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2721 .build());
2722 leftWindow->consumeMotionEvent(
2723 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2724
2725 // Stylus hovered on right window
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2729 .build());
2730 leftWindow->consumeMotionEvent(
2731 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2732 rightWindow->consumeMotionEvent(
2733 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2734
2735 // Subsequent HOVER_MOVE events are dispatched correctly.
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2737 .deviceId(mouseDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2739 .build());
2740 leftWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2742 rightWindow->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2744
2745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2746 .deviceId(stylusDeviceId)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2748 .build());
2749 leftWindow->consumeMotionEvent(
2750 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2751 rightWindow->consumeMotionEvent(
2752 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2753
2754 leftWindow->assertNoEvents();
2755 rightWindow->assertNoEvents();
2756}
2757
2758/**
2759 * Three windows: a window on the left and a window on the right.
2760 * And a spy window that's positioned above all of them.
2761 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2762 * Check the stream that's received by the spy.
2763 */
2764TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2766
2767 sp<FakeWindowHandle> spyWindow =
2768 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2769 spyWindow->setFrame(Rect(0, 0, 400, 400));
2770 spyWindow->setTrustedOverlay(true);
2771 spyWindow->setSpy(true);
2772
2773 sp<FakeWindowHandle> leftWindow =
2774 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2775 leftWindow->setFrame(Rect(0, 0, 200, 200));
2776
2777 sp<FakeWindowHandle> rightWindow =
2778 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2779
2780 rightWindow->setFrame(Rect(200, 0, 400, 200));
2781
2782 mDispatcher->onWindowInfosChanged(
2783 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2784
2785 const int32_t stylusDeviceId = 1;
2786 const int32_t touchDeviceId = 2;
2787
2788 // Stylus down on the left window
2789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2790 .deviceId(stylusDeviceId)
2791 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2792 .build());
2793 leftWindow->consumeMotionEvent(
2794 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2795 spyWindow->consumeMotionEvent(
2796 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2797
2798 // Touch down on the right window
2799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2800 .deviceId(touchDeviceId)
2801 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2802 .build());
2803 leftWindow->consumeMotionEvent(
2804 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2805 spyWindow->consumeMotionEvent(
2806 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2807 rightWindow->consumeMotionEvent(
2808 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2809 spyWindow->consumeMotionEvent(
2810 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2811
2812 // Stylus movements continue, but are ignored because the touch went down more recently.
2813 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2814 .deviceId(stylusDeviceId)
2815 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2816 .build());
2817
2818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2819 .deviceId(touchDeviceId)
2820 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2821 .build());
2822 rightWindow->consumeMotionEvent(
2823 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2824 spyWindow->consumeMotionEvent(
2825 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2826
2827 spyWindow->assertNoEvents();
2828 leftWindow->assertNoEvents();
2829 rightWindow->assertNoEvents();
2830}
2831
2832/**
2833 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2834 * both.
2835 * Check hover in left window and touch down in the right window.
2836 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2837 */
2838TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2840
2841 sp<FakeWindowHandle> spyWindow =
2842 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2843 spyWindow->setFrame(Rect(0, 0, 400, 400));
2844 spyWindow->setTrustedOverlay(true);
2845 spyWindow->setSpy(true);
2846
2847 sp<FakeWindowHandle> leftWindow =
2848 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2849 leftWindow->setFrame(Rect(0, 0, 200, 200));
2850
2851 sp<FakeWindowHandle> rightWindow =
2852 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2853 rightWindow->setFrame(Rect(200, 0, 400, 200));
2854
2855 mDispatcher->onWindowInfosChanged(
2856 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2857
2858 const int32_t stylusDeviceId = 1;
2859 const int32_t touchDeviceId = 2;
2860
2861 // Stylus hover on the left window
2862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2863 .deviceId(stylusDeviceId)
2864 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2865 .build());
2866 leftWindow->consumeMotionEvent(
2867 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2868 spyWindow->consumeMotionEvent(
2869 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2870
2871 // Touch down on the right window.
2872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2873 .deviceId(touchDeviceId)
2874 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2875 .build());
2876 leftWindow->consumeMotionEvent(
2877 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2878 spyWindow->consumeMotionEvent(
2879 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2880 spyWindow->consumeMotionEvent(
2881 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2882 rightWindow->consumeMotionEvent(
2883 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2884
2885 // Stylus movements continue, but are ignored because the touch is down.
2886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2887 .deviceId(stylusDeviceId)
2888 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2889 .build());
2890
2891 // Touch movements continue. They should be delivered to the right window and to the spy
2892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2893 .deviceId(touchDeviceId)
2894 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2895 .build());
2896 spyWindow->consumeMotionEvent(
2897 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2898 rightWindow->consumeMotionEvent(
2899 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2900
2901 spyWindow->assertNoEvents();
2902 leftWindow->assertNoEvents();
2903 rightWindow->assertNoEvents();
2904}
2905
2906/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002907 * On a single window, use two different devices: mouse and touch.
2908 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2909 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2910 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2911 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2912 * represent a new gesture.
2913 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002914TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2916 sp<FakeWindowHandle> window =
2917 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2918 window->setFrame(Rect(0, 0, 400, 400));
2919
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002920 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002921
2922 const int32_t touchDeviceId = 4;
2923 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002924
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002925 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2927 .deviceId(touchDeviceId)
2928 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2929 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002930 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002931 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2932 .deviceId(touchDeviceId)
2933 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2934 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2935 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002936 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002937 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2938 .deviceId(touchDeviceId)
2939 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2940 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2941 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002942 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2943 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2944 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2945
2946 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2948 .deviceId(mouseDeviceId)
2949 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2951 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002952
2953 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002954 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002955 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2956
Prabir Pradhan678438e2023-04-13 19:32:51 +00002957 mDispatcher->notifyMotion(
2958 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2959 .deviceId(mouseDeviceId)
2960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2961 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2963 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002964 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2965
2966 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002967 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2971 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002972 // Since we already canceled this touch gesture, it will be ignored until a completely new
2973 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2974 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2975 // However, mouse movements should continue to work.
2976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2977 .deviceId(mouseDeviceId)
2978 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2979 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2980 .build());
2981 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2982
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002983 window->assertNoEvents();
2984}
2985
2986/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002987 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2988 * the injected event.
2989 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002990TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2992 sp<FakeWindowHandle> window =
2993 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2994 window->setFrame(Rect(0, 0, 400, 400));
2995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002996 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002997
2998 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002999 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3000 // completion.
3001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003002 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003003 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3004 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003005 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003006 .build()));
3007 window->consumeMotionEvent(
3008 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3009
3010 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3011 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003012 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3013 .deviceId(touchDeviceId)
3014 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3015 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003016
3017 window->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3019 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3020}
3021
3022/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003023 * This test is similar to the test above, but the sequence of injected events is different.
3024 *
3025 * Two windows: a window on the left and a window on the right.
3026 * Mouse is hovered over the left window.
3027 * Next, we tap on the left window, where the cursor was last seen.
3028 *
3029 * After that, we inject one finger down onto the right window, and then a second finger down onto
3030 * the left window.
3031 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3032 * window (first), and then another on the left window (second).
3033 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3034 * In the buggy implementation, second finger down on the left window would cause a crash.
3035 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003036TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3038 sp<FakeWindowHandle> leftWindow =
3039 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3040 leftWindow->setFrame(Rect(0, 0, 200, 200));
3041
3042 sp<FakeWindowHandle> rightWindow =
3043 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3044 rightWindow->setFrame(Rect(200, 0, 400, 200));
3045
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003046 mDispatcher->onWindowInfosChanged(
3047 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003048
3049 const int32_t mouseDeviceId = 6;
3050 const int32_t touchDeviceId = 4;
3051 // Hover over the left window. Keep the cursor there.
3052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003053 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003054 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3055 AINPUT_SOURCE_MOUSE)
3056 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003057 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003058 .build()));
3059 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3060
3061 // Tap on left window
3062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003063 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003064 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3065 AINPUT_SOURCE_TOUCHSCREEN)
3066 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003067 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003068 .build()));
3069
3070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003071 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003072 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3073 AINPUT_SOURCE_TOUCHSCREEN)
3074 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003075 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003076 .build()));
3077 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3078 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3079 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3080
3081 // First finger down on right window
3082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003083 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003084 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3085 AINPUT_SOURCE_TOUCHSCREEN)
3086 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003087 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003088 .build()));
3089 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3090
3091 // Second finger down on the left window
3092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003093 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003094 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3095 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003096 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3097 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003098 .build()));
3099 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3100 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3101
3102 // No more events
3103 leftWindow->assertNoEvents();
3104 rightWindow->assertNoEvents();
3105}
3106
3107/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003108 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3109 * While the touch is down, new hover events from the stylus device should be ignored. After the
3110 * touch is gone, stylus hovering should start working again.
3111 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003112TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3114 sp<FakeWindowHandle> window =
3115 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3116 window->setFrame(Rect(0, 0, 200, 200));
3117
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003118 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003119
3120 const int32_t stylusDeviceId = 5;
3121 const int32_t touchDeviceId = 4;
3122 // Start hovering with stylus
3123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003124 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003125 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003126 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003127 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003128 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003129 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003130
3131 // Finger down on the window
3132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003133 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003134 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003135 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003136 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003137 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003138 window->consumeMotionEvent(
3139 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3140 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003141
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003142 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003143 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003144 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003145 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3146 AINPUT_SOURCE_STYLUS)
3147 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003148 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003149 .build()));
3150 // No event should be sent. This event should be ignored because a pointer from another device
3151 // is already down.
3152
3153 // Lift up the finger
3154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003155 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003156 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3157 AINPUT_SOURCE_TOUCHSCREEN)
3158 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003159 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003160 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003161 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003162
3163 // Now that the touch is gone, stylus hovering should start working again
3164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003165 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003166 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3167 AINPUT_SOURCE_STYLUS)
3168 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003169 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003170 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003171 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3172 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003173 window->assertNoEvents();
3174}
3175
3176/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003177 * A spy window above a window with no input channel.
3178 * Start hovering with a stylus device, and then tap with it.
3179 * Ensure spy window receives the entire sequence.
3180 */
3181TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3182 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3183 sp<FakeWindowHandle> spyWindow =
3184 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3185 spyWindow->setFrame(Rect(0, 0, 200, 200));
3186 spyWindow->setTrustedOverlay(true);
3187 spyWindow->setSpy(true);
3188 sp<FakeWindowHandle> window =
3189 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3190 window->setNoInputChannel(true);
3191 window->setFrame(Rect(0, 0, 200, 200));
3192
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003193 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003194
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003195 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3197 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3198 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3200 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003201 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3202 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3203 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003204 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3205
3206 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3208 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3209 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003210 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3211
3212 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3214 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3215 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003216 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3217
3218 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3220 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3221 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003222 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3223 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003224 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3225 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3226 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003227 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3228
3229 // No more events
3230 spyWindow->assertNoEvents();
3231 window->assertNoEvents();
3232}
3233
3234/**
3235 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3236 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3237 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3238 * While the mouse is down, new move events from the touch device should be ignored.
3239 */
3240TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3242 sp<FakeWindowHandle> spyWindow =
3243 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3244 spyWindow->setFrame(Rect(0, 0, 200, 200));
3245 spyWindow->setTrustedOverlay(true);
3246 spyWindow->setSpy(true);
3247 sp<FakeWindowHandle> window =
3248 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3249 window->setFrame(Rect(0, 0, 200, 200));
3250
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003251 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003252
3253 const int32_t mouseDeviceId = 7;
3254 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003255
3256 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3258 .deviceId(mouseDeviceId)
3259 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3260 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003261 spyWindow->consumeMotionEvent(
3262 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3263 window->consumeMotionEvent(
3264 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3265
3266 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3268 .deviceId(touchDeviceId)
3269 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3270 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003271 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3272 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3273 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3274 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3275
Prabir Pradhan678438e2023-04-13 19:32:51 +00003276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3277 .deviceId(touchDeviceId)
3278 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3279 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003280 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3281 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3282
3283 // Pilfer the stream
3284 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3285 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3286
Prabir Pradhan678438e2023-04-13 19:32:51 +00003287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3288 .deviceId(touchDeviceId)
3289 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3290 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003291 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3292
3293 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003294 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3295 .deviceId(mouseDeviceId)
3296 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3297 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3298 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003299
3300 spyWindow->consumeMotionEvent(
3301 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3302 spyWindow->consumeMotionEvent(
3303 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3304 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3305
Prabir Pradhan678438e2023-04-13 19:32:51 +00003306 mDispatcher->notifyMotion(
3307 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3308 .deviceId(mouseDeviceId)
3309 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3310 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3311 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3312 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003313 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3314 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3315
3316 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003317 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3318 .deviceId(mouseDeviceId)
3319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3321 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003322 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3323 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3324
3325 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3327 .deviceId(touchDeviceId)
3328 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3329 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003330
3331 // No more events
3332 spyWindow->assertNoEvents();
3333 window->assertNoEvents();
3334}
3335
3336/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003337 * On the display, have a single window, and also an area where there's no window.
3338 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3339 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3340 */
3341TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003344 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003345
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003346 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003347
3348 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003349 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003350
3351 mDispatcher->waitForIdle();
3352 window->assertNoEvents();
3353
3354 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003355 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003356 mDispatcher->waitForIdle();
3357 window->consumeMotionDown();
3358}
3359
3360/**
3361 * Same test as above, but instead of touching the empty space, the first touch goes to
3362 * non-touchable window.
3363 */
3364TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3366 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003367 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003368 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3369 window1->setTouchable(false);
3370 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003371 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003372 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3373
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003374 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003375
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003376 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003377 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003378
3379 mDispatcher->waitForIdle();
3380 window1->assertNoEvents();
3381 window2->assertNoEvents();
3382
3383 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003384 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003385 mDispatcher->waitForIdle();
3386 window2->consumeMotionDown();
3387}
3388
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003389/**
3390 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3391 * to the event time of the first ACTION_DOWN sent to the particular window.
3392 */
3393TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3395 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003396 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003397 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3398 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003400 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003402 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003403
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003404 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003405 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003406
3407 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003408
3409 MotionEvent* motionEvent1 = window1->consumeMotion();
3410 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003411 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003412 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3413 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003414
3415 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003416 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003417 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003418 MotionEvent* motionEvent2 = window2->consumeMotion();
3419 ASSERT_NE(motionEvent2, nullptr);
3420 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003421 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003422 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003423
3424 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003425 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003426 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003427 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003428
3429 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003430 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003431 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003432 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003433
3434 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3435 window1->consumeMotionMove();
3436 window1->assertNoEvents();
3437
3438 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003439 mDispatcher->notifyMotion(
3440 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003441 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003442 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003443
Prabir Pradhan678438e2023-04-13 19:32:51 +00003444 mDispatcher->notifyMotion(
3445 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003446 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003447 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003448}
3449
Garfield Tandf26e862020-07-01 20:18:19 -07003450TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003452 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003453 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003454 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003455 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003456 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003457 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003458
3459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3460
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003461 mDispatcher->onWindowInfosChanged(
3462 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003463
3464 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003466 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003467 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3468 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003469 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003470 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003471 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003472
3473 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003475 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003476 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3477 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003478 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003479 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003480 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3481 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003482
3483 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003485 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003486 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3487 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003488 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003489 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003490 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3491 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003492
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003494 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003495 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3496 AINPUT_SOURCE_MOUSE)
3497 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3498 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003499 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003500 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003501 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003502
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003504 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003505 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3506 AINPUT_SOURCE_MOUSE)
3507 .buttonState(0)
3508 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003509 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003510 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003511 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003514 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003515 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3516 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003517 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003518 .build()));
3519 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3520
3521 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003523 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003524 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3525 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003526 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003527 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003528 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003529
3530 // No more events
3531 windowLeft->assertNoEvents();
3532 windowRight->assertNoEvents();
3533}
3534
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003535/**
3536 * Put two fingers down (and don't release them) and click the mouse button.
3537 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3538 * currently active gesture should be canceled, and the new one should proceed.
3539 */
3540TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3542 sp<FakeWindowHandle> window =
3543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3544 window->setFrame(Rect(0, 0, 600, 800));
3545
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003546 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003547
3548 const int32_t touchDeviceId = 4;
3549 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003550
3551 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3553 .deviceId(touchDeviceId)
3554 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3555 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003556
Prabir Pradhan678438e2023-04-13 19:32:51 +00003557 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3558 .deviceId(touchDeviceId)
3559 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3560 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3561 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003562 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3563 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3564
3565 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3567 .deviceId(mouseDeviceId)
3568 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3569 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3570 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003571 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3572 WithPointerCount(2u)));
3573 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3574
Prabir Pradhan678438e2023-04-13 19:32:51 +00003575 mDispatcher->notifyMotion(
3576 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3577 .deviceId(mouseDeviceId)
3578 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3579 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3580 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3581 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003582 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3583
3584 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3585 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003586 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3587 .deviceId(touchDeviceId)
3588 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3589 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3590 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003591 window->assertNoEvents();
3592}
3593
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003594TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3596
3597 sp<FakeWindowHandle> spyWindow =
3598 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3599 spyWindow->setFrame(Rect(0, 0, 600, 800));
3600 spyWindow->setTrustedOverlay(true);
3601 spyWindow->setSpy(true);
3602 sp<FakeWindowHandle> window =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3604 window->setFrame(Rect(0, 0, 600, 800));
3605
3606 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003607 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003608
3609 // Send mouse cursor to the window
3610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003611 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003612 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3613 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003615 .build()));
3616
3617 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3618 WithSource(AINPUT_SOURCE_MOUSE)));
3619 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3620 WithSource(AINPUT_SOURCE_MOUSE)));
3621
3622 window->assertNoEvents();
3623 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003624}
3625
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003626TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3628
3629 sp<FakeWindowHandle> spyWindow =
3630 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3631 spyWindow->setFrame(Rect(0, 0, 600, 800));
3632 spyWindow->setTrustedOverlay(true);
3633 spyWindow->setSpy(true);
3634 sp<FakeWindowHandle> window =
3635 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3636 window->setFrame(Rect(0, 0, 600, 800));
3637
3638 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003639 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003640
3641 // Send mouse cursor to the window
3642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003643 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003644 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3645 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003646 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003647 .build()));
3648
3649 // Move mouse cursor
3650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003651 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003652 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3653 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003654 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003655 .build()));
3656
3657 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3658 WithSource(AINPUT_SOURCE_MOUSE)));
3659 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3660 WithSource(AINPUT_SOURCE_MOUSE)));
3661 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3662 WithSource(AINPUT_SOURCE_MOUSE)));
3663 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3664 WithSource(AINPUT_SOURCE_MOUSE)));
3665 // Touch down on the window
3666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003667 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003668 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3669 AINPUT_SOURCE_TOUCHSCREEN)
3670 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003671 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003672 .build()));
3673 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3674 WithSource(AINPUT_SOURCE_MOUSE)));
3675 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3676 WithSource(AINPUT_SOURCE_MOUSE)));
3677 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3678 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3679 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3680 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3681
3682 // pilfer the motion, retaining the gesture on the spy window.
3683 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3684 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3685 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3686
3687 // Touch UP on the window
3688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003689 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003690 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3691 AINPUT_SOURCE_TOUCHSCREEN)
3692 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003693 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003694 .build()));
3695 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3696 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3697
3698 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3699 // to send a new gesture. It should again go to both windows (spy and the window below), just
3700 // like the first gesture did, before pilfering. The window configuration has not changed.
3701
3702 // One more tap - DOWN
3703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003704 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003705 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3706 AINPUT_SOURCE_TOUCHSCREEN)
3707 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003708 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003709 .build()));
3710 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3711 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3712 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3713 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3714
3715 // Touch UP on the window
3716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003717 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003718 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3719 AINPUT_SOURCE_TOUCHSCREEN)
3720 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003721 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003722 .build()));
3723 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3724 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3725 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3726 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3727
3728 window->assertNoEvents();
3729 spyWindow->assertNoEvents();
3730}
3731
Garfield Tandf26e862020-07-01 20:18:19 -07003732// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3733// directly in this test.
3734TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003736 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003737 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003738 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003739
3740 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3741
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003742 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003743
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003745 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003746 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3747 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003748 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003749 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003750 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003751 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003753 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003754 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3755 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003756 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003757 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003758 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3759 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003760
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003762 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003763 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3764 AINPUT_SOURCE_MOUSE)
3765 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3766 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003767 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003768 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003769 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003770
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003772 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003773 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3774 AINPUT_SOURCE_MOUSE)
3775 .buttonState(0)
3776 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003777 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003778 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003779 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003780
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003782 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003783 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3784 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003785 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003786 .build()));
3787 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3788
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003789 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3790 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3791 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003792 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003793 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3794 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003795 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003796 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003797 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003798}
3799
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003800/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003801 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3802 * is generated.
3803 */
3804TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3806 sp<FakeWindowHandle> window =
3807 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3808 window->setFrame(Rect(0, 0, 1200, 800));
3809
3810 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3811
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003812 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003813
3814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003815 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003816 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3817 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003818 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003819 .build()));
3820 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3821
3822 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003823 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003824 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3825}
3826
3827/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003828 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3829 */
3830TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3832 sp<FakeWindowHandle> window =
3833 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3834 window->setFrame(Rect(0, 0, 1200, 800));
3835
3836 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3837
3838 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3839
3840 MotionEventBuilder hoverEnterBuilder =
3841 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3842 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3843 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3845 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3847 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3848 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3849 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3850}
3851
3852/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003853 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3854 */
3855TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3857 sp<FakeWindowHandle> window =
3858 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3859 window->setFrame(Rect(0, 0, 100, 100));
3860
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003861 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003862
3863 const int32_t mouseDeviceId = 7;
3864 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003865
3866 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3868 .deviceId(mouseDeviceId)
3869 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3870 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003871 window->consumeMotionEvent(
3872 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3873
3874 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3876 .deviceId(touchDeviceId)
3877 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3878 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003879
3880 window->consumeMotionEvent(
3881 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3882 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3883}
3884
3885/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003886 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003887 * The tap causes a HOVER_EXIT event to be generated because the current event
3888 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003889 */
3890TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3892 sp<FakeWindowHandle> window =
3893 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3894 window->setFrame(Rect(0, 0, 100, 100));
3895
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3898 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3899 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003900 ASSERT_NO_FATAL_FAILURE(
3901 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3902 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003903
3904 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3907 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003908 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003909 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3910 WithSource(AINPUT_SOURCE_MOUSE))));
3911
3912 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003913 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3914 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3915
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3917 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3918 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003919 ASSERT_NO_FATAL_FAILURE(
3920 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3921 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3922}
3923
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003924TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3926 sp<FakeWindowHandle> windowDefaultDisplay =
3927 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3928 ADISPLAY_ID_DEFAULT);
3929 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3930 sp<FakeWindowHandle> windowSecondDisplay =
3931 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3932 SECOND_DISPLAY_ID);
3933 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3934
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003935 mDispatcher->onWindowInfosChanged(
3936 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003937
3938 // Set cursor position in window in default display and check that hover enter and move
3939 // events are generated.
3940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003941 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003942 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3943 AINPUT_SOURCE_MOUSE)
3944 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003945 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003946 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003947 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003948
3949 // Remove all windows in secondary display and check that no event happens on window in
3950 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003951 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3952
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003953 windowDefaultDisplay->assertNoEvents();
3954
3955 // Move cursor position in window in default display and check that only hover move
3956 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003957 mDispatcher->onWindowInfosChanged(
3958 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003960 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003961 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3962 AINPUT_SOURCE_MOUSE)
3963 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003965 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003966 windowDefaultDisplay->consumeMotionEvent(
3967 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3968 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003969 windowDefaultDisplay->assertNoEvents();
3970}
3971
Garfield Tan00f511d2019-06-12 16:55:40 -07003972TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003974
3975 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003977 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003978 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003979 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003980 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003981
3982 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3983
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003984 mDispatcher->onWindowInfosChanged(
3985 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003986
3987 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3988 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003990 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003991 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003992 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003993 windowRight->assertNoEvents();
3994}
3995
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003996TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003998 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3999 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004000 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004001
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004002 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004003 setFocusedWindow(window);
4004
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004005 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004006
Prabir Pradhan678438e2023-04-13 19:32:51 +00004007 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004008
4009 // Window should receive key down event.
4010 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4011
4012 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4013 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004014 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004015 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004016 AKEY_EVENT_FLAG_CANCELED);
4017}
4018
4019TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004021 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4022 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004023
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004024 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004025
Prabir Pradhan678438e2023-04-13 19:32:51 +00004026 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4027 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004028
4029 // Window should receive motion down event.
4030 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4031
4032 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4033 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004034 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004035 window->consumeMotionEvent(
4036 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004037}
4038
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004039TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4041 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4042 "Fake Window", ADISPLAY_ID_DEFAULT);
4043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004044 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004045
4046 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4047 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4048 .build());
4049
4050 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4051
4052 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4053 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4054 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4055
4056 // After the device has been reset, a new hovering stream can be sent to the window
4057 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4058 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4059 .build());
4060 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4061}
4062
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004063TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004065 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4066 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004067 window->setFocusable(true);
4068
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004069 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004070 setFocusedWindow(window);
4071
4072 window->consumeFocusEvent(true);
4073
Prabir Pradhan678438e2023-04-13 19:32:51 +00004074 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004075 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4076 const nsecs_t injectTime = keyArgs.eventTime;
4077 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004078 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004079 // The dispatching time should be always greater than or equal to intercept key timeout.
4080 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4081 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4082 std::chrono::nanoseconds(interceptKeyTimeout).count());
4083}
4084
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004085/**
4086 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4087 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004088TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004090 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4091 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004092 window->setFocusable(true);
4093
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004094 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004095 setFocusedWindow(window);
4096
4097 window->consumeFocusEvent(true);
4098
Prabir Pradhan678438e2023-04-13 19:32:51 +00004099 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004100 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004101
4102 // Set a value that's significantly larger than the default consumption timeout. If the
4103 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4104 mFakePolicy->setInterceptKeyTimeout(600ms);
4105 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4106 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004107 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4108}
4109
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004110/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004111 * Two windows. First is a regular window. Second does not overlap with the first, and has
4112 * WATCH_OUTSIDE_TOUCH.
4113 * Both windows are owned by the same UID.
4114 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4115 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4116 */
4117TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004119 sp<FakeWindowHandle> window =
4120 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004121 window->setFrame(Rect{0, 0, 100, 100});
4122
4123 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004124 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004125 ADISPLAY_ID_DEFAULT);
4126 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4127 outsideWindow->setWatchOutsideTouch(true);
4128 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004129 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004130
4131 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004132 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4133 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4134 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004135 window->consumeMotionDown();
4136 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4137 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4138 outsideWindow->consumeMotionEvent(
4139 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4140}
4141
4142/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004143 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4144 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4145 * ACTION_OUTSIDE event is sent per gesture.
4146 */
4147TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4148 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004150 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4151 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004152 window->setWatchOutsideTouch(true);
4153 window->setFrame(Rect{0, 0, 100, 100});
4154 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004155 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4156 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004157 secondWindow->setFrame(Rect{100, 100, 200, 200});
4158 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004159 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4160 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004161 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004162 mDispatcher->onWindowInfosChanged(
4163 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004164
4165 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4167 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4168 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004169 window->assertNoEvents();
4170 secondWindow->assertNoEvents();
4171
4172 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4173 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004174 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4175 ADISPLAY_ID_DEFAULT,
4176 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004177 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4178 window->consumeMotionEvent(
4179 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004180 secondWindow->consumeMotionDown();
4181 thirdWindow->assertNoEvents();
4182
4183 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4184 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004185 mDispatcher->notifyMotion(
4186 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4187 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004188 window->assertNoEvents();
4189 secondWindow->consumeMotionMove();
4190 thirdWindow->consumeMotionDown();
4191}
4192
Prabir Pradhan814fe082022-07-22 20:22:18 +00004193TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004195 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4196 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004197 window->setFocusable(true);
4198
Patrick Williamsd828f302023-04-28 17:52:08 -05004199 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004200 setFocusedWindow(window);
4201
4202 window->consumeFocusEvent(true);
4203
Prabir Pradhan678438e2023-04-13 19:32:51 +00004204 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4205 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4206 mDispatcher->notifyKey(keyDown);
4207 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004208
4209 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4210 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4211
4212 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004213 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004214
4215 window->consumeFocusEvent(false);
4216
Prabir Pradhan678438e2023-04-13 19:32:51 +00004217 mDispatcher->notifyKey(keyDown);
4218 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004219 window->assertNoEvents();
4220}
4221
Arthur Hung96483742022-11-15 03:30:48 +00004222TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4224 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4225 "Fake Window", ADISPLAY_ID_DEFAULT);
4226 // Ensure window is non-split and have some transform.
4227 window->setPreventSplitting(true);
4228 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004229 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004230
4231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004232 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004233 {50, 50}))
4234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4235 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4236
4237 const MotionEvent secondFingerDownEvent =
4238 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4239 .displayId(ADISPLAY_ID_DEFAULT)
4240 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004241 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4242 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004243 .build();
4244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004245 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004246 InputEventInjectionSync::WAIT_FOR_RESULT))
4247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4248
4249 const MotionEvent* event = window->consumeMotion();
4250 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4251 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4252 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4253 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4254 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4255}
4256
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004257/**
4258 * Two windows: a splittable and a non-splittable.
4259 * The non-splittable window shouldn't receive any "incomplete" gestures.
4260 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4261 * The second pointer should be dropped because the initial window is splittable, so it won't get
4262 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4263 * "incomplete" gestures.
4264 */
4265TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4267 sp<FakeWindowHandle> leftWindow =
4268 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4269 ADISPLAY_ID_DEFAULT);
4270 leftWindow->setPreventSplitting(false);
4271 leftWindow->setFrame(Rect(0, 0, 100, 100));
4272 sp<FakeWindowHandle> rightWindow =
4273 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4274 ADISPLAY_ID_DEFAULT);
4275 rightWindow->setPreventSplitting(true);
4276 rightWindow->setFrame(Rect(100, 100, 200, 200));
4277 mDispatcher->onWindowInfosChanged(
4278 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4279
4280 // Touch down on left, splittable window
4281 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4282 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4283 .build());
4284 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4285
4286 mDispatcher->notifyMotion(
4287 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4288 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4289 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4290 .build());
4291 leftWindow->assertNoEvents();
4292 rightWindow->assertNoEvents();
4293}
4294
Harry Cuttsb166c002023-05-09 13:06:05 +00004295TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4296 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4297 sp<FakeWindowHandle> window =
4298 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4299 window->setFrame(Rect(0, 0, 400, 400));
4300 sp<FakeWindowHandle> trustedOverlay =
4301 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4302 ADISPLAY_ID_DEFAULT);
4303 trustedOverlay->setSpy(true);
4304 trustedOverlay->setTrustedOverlay(true);
4305
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004306 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004307
4308 // Start a three-finger touchpad swipe
4309 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4310 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4311 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4312 .build());
4313 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4314 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4315 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4316 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4317 .build());
4318 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4319 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4320 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4321 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4322 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4323 .build());
4324
4325 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4326 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4327 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4328
4329 // Move the swipe a bit
4330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4331 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4332 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4333 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4334 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4335 .build());
4336
4337 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4338
4339 // End the swipe
4340 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4341 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4342 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4343 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4344 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4345 .build());
4346 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4347 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4348 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4349 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4350 .build());
4351 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4352 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4353 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4354 .build());
4355
4356 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4357 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4358 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4359
4360 window->assertNoEvents();
4361}
4362
4363TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4365 sp<FakeWindowHandle> window =
4366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4367 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004369
4370 // Start a three-finger touchpad swipe
4371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4372 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4373 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4374 .build());
4375 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4376 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4377 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4378 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4379 .build());
4380 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4381 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4382 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4383 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4384 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4385 .build());
4386
4387 // Move the swipe a bit
4388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4389 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4390 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4391 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4392 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4393 .build());
4394
4395 // End the swipe
4396 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4397 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4398 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4399 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4400 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4401 .build());
4402 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4403 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4404 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4405 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4406 .build());
4407 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4408 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4409 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4410 .build());
4411
4412 window->assertNoEvents();
4413}
4414
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004415/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004416 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4417 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004418 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004419 */
4420TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4422 sp<FakeWindowHandle> window =
4423 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4424 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004425 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004426
4427 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4428 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4429 .downTime(baseTime + 10)
4430 .eventTime(baseTime + 10)
4431 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4432 .build());
4433
4434 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4435
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004436 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004437 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004438
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004440
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004441 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4442 .downTime(baseTime + 10)
4443 .eventTime(baseTime + 30)
4444 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4445 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4446 .build());
4447
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004448 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4449
4450 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004451 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4452 .downTime(baseTime + 10)
4453 .eventTime(baseTime + 40)
4454 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4455 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4456 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004457
4458 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4459
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4461 .downTime(baseTime + 10)
4462 .eventTime(baseTime + 50)
4463 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4464 .build());
4465
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004466 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4467
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4469 .downTime(baseTime + 60)
4470 .eventTime(baseTime + 60)
4471 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4472 .build());
4473
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004474 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004475}
4476
4477/**
Hu Guo771a7692023-09-17 20:51:08 +08004478 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4479 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4480 * its coordinates should be converted by the transform of the windows of target screen.
4481 */
4482TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4483 // This case will create a window and a spy window on the default display and mirror
4484 // window on the second display. cancel event is sent through spy window pilferPointers
4485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4486
4487 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4488 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4489 spyWindowDefaultDisplay->setTrustedOverlay(true);
4490 spyWindowDefaultDisplay->setSpy(true);
4491
4492 sp<FakeWindowHandle> windowDefaultDisplay =
4493 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4494 ADISPLAY_ID_DEFAULT);
4495 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4496
4497 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4498 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4499
4500 // Add the windows to the dispatcher
4501 mDispatcher->onWindowInfosChanged(
4502 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4503 *windowSecondDisplay->getInfo()},
4504 {},
4505 0,
4506 0});
4507
4508 // Send down to ADISPLAY_ID_DEFAULT
4509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4510 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4511 {100, 100}))
4512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4513
4514 spyWindowDefaultDisplay->consumeMotionDown();
4515 windowDefaultDisplay->consumeMotionDown();
4516
4517 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4518
4519 // windowDefaultDisplay gets cancel
4520 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4521 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4522
4523 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4524 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4525 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4526 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4527 EXPECT_EQ(100, event->getX(0));
4528 EXPECT_EQ(100, event->getY(0));
4529}
4530
4531/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004532 * Ensure the correct coordinate spaces are used by InputDispatcher.
4533 *
4534 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4535 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4536 * space.
4537 */
4538class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4539public:
4540 void SetUp() override {
4541 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004542 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004543 }
4544
4545 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4546 gui::DisplayInfo info;
4547 info.displayId = displayId;
4548 info.transform = transform;
4549 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004550 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004551 }
4552
4553 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4554 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004555 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004556 }
4557
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004558 void removeAllWindowsAndDisplays() {
4559 mDisplayInfos.clear();
4560 mWindowInfos.clear();
4561 }
4562
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004563 // Set up a test scenario where the display has a scaled projection and there are two windows
4564 // on the display.
4565 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4566 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4567 // respectively.
4568 ui::Transform displayTransform;
4569 displayTransform.set(2, 0, 0, 4);
4570 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4571
4572 std::shared_ptr<FakeApplicationHandle> application =
4573 std::make_shared<FakeApplicationHandle>();
4574
4575 // Add two windows to the display. Their frames are represented in the display space.
4576 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004577 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4578 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004579 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4580 addWindow(firstWindow);
4581
4582 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004583 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4584 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004585 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4586 addWindow(secondWindow);
4587 return {std::move(firstWindow), std::move(secondWindow)};
4588 }
4589
4590private:
4591 std::vector<gui::DisplayInfo> mDisplayInfos;
4592 std::vector<gui::WindowInfo> mWindowInfos;
4593};
4594
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004595TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004596 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4597 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004598 // selected so that if the hit test was performed with the point and the bounds being in
4599 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004600 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4601 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4602 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004603
4604 firstWindow->consumeMotionDown();
4605 secondWindow->assertNoEvents();
4606}
4607
4608// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4609// the event should be treated as being in the logical display space.
4610TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4611 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4612 // Send down to the first window. The point is represented in the logical display space. The
4613 // point is selected so that if the hit test was done in logical display space, then it would
4614 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004615 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004616 PointF{75 * 2, 55 * 4});
4617
4618 firstWindow->consumeMotionDown();
4619 secondWindow->assertNoEvents();
4620}
4621
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004622// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4623// event should be treated as being in the logical display space.
4624TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4625 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4626
4627 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4628 ui::Transform injectedEventTransform;
4629 injectedEventTransform.set(matrix);
4630 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4631 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4632
4633 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4634 .displayId(ADISPLAY_ID_DEFAULT)
4635 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004636 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004637 .x(untransformedPoint.x)
4638 .y(untransformedPoint.y))
4639 .build();
4640 event.transform(matrix);
4641
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004642 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004643 InputEventInjectionSync::WAIT_FOR_RESULT);
4644
4645 firstWindow->consumeMotionDown();
4646 secondWindow->assertNoEvents();
4647}
4648
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004649TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4650 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4651
4652 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004653 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4654 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4655 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004656
4657 firstWindow->assertNoEvents();
4658 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004659 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004660 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4661
4662 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4663 EXPECT_EQ(300, event->getRawX(0));
4664 EXPECT_EQ(880, event->getRawY(0));
4665
4666 // Ensure that the x and y values are in the window's coordinate space.
4667 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4668 // the logical display space. This will be the origin of the window space.
4669 EXPECT_EQ(100, event->getX(0));
4670 EXPECT_EQ(80, event->getY(0));
4671}
4672
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004673TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4674 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4675 // The monitor will always receive events in the logical display's coordinate space, because
4676 // it does not have a window.
4677 FakeMonitorReceiver monitor{mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
4678
4679 // Send down to the first window.
4680 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4681 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4682 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4683 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4684
4685 // Second pointer goes down on second window.
4686 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4687 ADISPLAY_ID_DEFAULT,
4688 {PointF{50, 100}, PointF{150, 220}}));
4689 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4690 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4691 {1, PointF{300, 880}}};
4692 monitor.consumeMotionEvent(
4693 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4694
4695 mDispatcher->cancelCurrentTouch();
4696
4697 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4698 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4699 monitor.consumeMotionEvent(
4700 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4701}
4702
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004703/** Ensure consistent behavior of InputDispatcher in all orientations. */
4704class InputDispatcherDisplayOrientationFixture
4705 : public InputDispatcherDisplayProjectionTest,
4706 public ::testing::WithParamInterface<ui::Rotation> {};
4707
4708// This test verifies the touchable region of a window for all rotations of the display by tapping
4709// in different locations on the display, specifically points close to the four corners of a
4710// window.
4711TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4712 constexpr static int32_t displayWidth = 400;
4713 constexpr static int32_t displayHeight = 800;
4714
4715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4716
4717 const auto rotation = GetParam();
4718
4719 // Set up the display with the specified rotation.
4720 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4721 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4722 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4723 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4724 logicalDisplayWidth, logicalDisplayHeight);
4725 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4726
4727 // Create a window with its bounds determined in the logical display.
4728 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4729 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4730 sp<FakeWindowHandle> window =
4731 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4732 window->setFrame(frameInDisplay, displayTransform);
4733 addWindow(window);
4734
4735 // The following points in logical display space should be inside the window.
4736 static const std::array<vec2, 4> insidePoints{
4737 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4738 for (const auto pointInsideWindow : insidePoints) {
4739 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4740 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004741 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4742 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4743 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004744 window->consumeMotionDown();
4745
Prabir Pradhan678438e2023-04-13 19:32:51 +00004746 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4747 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4748 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004749 window->consumeMotionUp();
4750 }
4751
4752 // The following points in logical display space should be outside the window.
4753 static const std::array<vec2, 5> outsidePoints{
4754 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4755 for (const auto pointOutsideWindow : outsidePoints) {
4756 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4757 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004758 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4759 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4760 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004761
Prabir Pradhan678438e2023-04-13 19:32:51 +00004762 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4763 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4764 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004765 }
4766 window->assertNoEvents();
4767}
4768
4769// Run the precision tests for all rotations.
4770INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4771 InputDispatcherDisplayOrientationFixture,
4772 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4773 ui::ROTATION_270),
4774 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4775 return ftl::enum_string(testParamInfo.param);
4776 });
4777
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004778using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4779 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004780
4781class TransferTouchFixture : public InputDispatcherTest,
4782 public ::testing::WithParamInterface<TransferFunction> {};
4783
4784TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004786
4787 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004788 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004789 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4790 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004791 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004792 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004793 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4794 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004795 sp<FakeWindowHandle> wallpaper =
4796 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4797 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004798 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004799 mDispatcher->onWindowInfosChanged(
4800 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004801
4802 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004803 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4804 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004805
Svet Ganov5d3bc372020-01-26 23:11:07 -08004806 // Only the first window should get the down event
4807 firstWindow->consumeMotionDown();
4808 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004809 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004810
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004811 // Transfer touch to the second window
4812 TransferFunction f = GetParam();
4813 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4814 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004815 // The first window gets cancel and the second gets down
4816 firstWindow->consumeMotionCancel();
4817 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004818 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004819
4820 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004821 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4822 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004823 // The first window gets no events and the second gets up
4824 firstWindow->assertNoEvents();
4825 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004826 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004827}
4828
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004829/**
4830 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4831 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4832 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4833 * natural to the user.
4834 * In this test, we are sending a pointer to both spy window and first window. We then try to
4835 * transfer touch to the second window. The dispatcher should identify the first window as the
4836 * one that should lose the gesture, and therefore the action should be to move the gesture from
4837 * the first window to the second.
4838 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4839 * the other API, as well.
4840 */
4841TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4842 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4843
4844 // Create a couple of windows + a spy window
4845 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004846 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004847 spyWindow->setTrustedOverlay(true);
4848 spyWindow->setSpy(true);
4849 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004850 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004851 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004852 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004853
4854 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004855 mDispatcher->onWindowInfosChanged(
4856 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004857
4858 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004859 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4860 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004861 // Only the first window and spy should get the down event
4862 spyWindow->consumeMotionDown();
4863 firstWindow->consumeMotionDown();
4864
4865 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4866 // if f === 'transferTouch'.
4867 TransferFunction f = GetParam();
4868 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4869 ASSERT_TRUE(success);
4870 // The first window gets cancel and the second gets down
4871 firstWindow->consumeMotionCancel();
4872 secondWindow->consumeMotionDown();
4873
4874 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004875 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4876 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004877 // The first window gets no events and the second+spy get up
4878 firstWindow->assertNoEvents();
4879 spyWindow->consumeMotionUp();
4880 secondWindow->consumeMotionUp();
4881}
4882
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004883TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004885
4886 PointF touchPoint = {10, 10};
4887
4888 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004889 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004890 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4891 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004892 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004893 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004894 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4895 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004896 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004897
4898 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004899 mDispatcher->onWindowInfosChanged(
4900 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004901
4902 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004903 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4904 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4905 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004906 // Only the first window should get the down event
4907 firstWindow->consumeMotionDown();
4908 secondWindow->assertNoEvents();
4909
4910 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004911 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4912 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004913 // Only the first window should get the pointer down event
4914 firstWindow->consumeMotionPointerDown(1);
4915 secondWindow->assertNoEvents();
4916
4917 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004918 TransferFunction f = GetParam();
4919 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4920 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004921 // The first window gets cancel and the second gets down and pointer down
4922 firstWindow->consumeMotionCancel();
4923 secondWindow->consumeMotionDown();
4924 secondWindow->consumeMotionPointerDown(1);
4925
4926 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004927 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4928 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004929 // The first window gets nothing and the second gets pointer up
4930 firstWindow->assertNoEvents();
4931 secondWindow->consumeMotionPointerUp(1);
4932
4933 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004934 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4935 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004936 // The first window gets nothing and the second gets up
4937 firstWindow->assertNoEvents();
4938 secondWindow->consumeMotionUp();
4939}
4940
Arthur Hungc539dbb2022-12-08 07:45:36 +00004941TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4943
4944 // Create a couple of windows
4945 sp<FakeWindowHandle> firstWindow =
4946 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4947 ADISPLAY_ID_DEFAULT);
4948 firstWindow->setDupTouchToWallpaper(true);
4949 sp<FakeWindowHandle> secondWindow =
4950 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4951 ADISPLAY_ID_DEFAULT);
4952 secondWindow->setDupTouchToWallpaper(true);
4953
4954 sp<FakeWindowHandle> wallpaper1 =
4955 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4956 wallpaper1->setIsWallpaper(true);
4957
4958 sp<FakeWindowHandle> wallpaper2 =
4959 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4960 wallpaper2->setIsWallpaper(true);
4961 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004962 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4963 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4964 {},
4965 0,
4966 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004967
4968 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004969 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4970 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004971
4972 // Only the first window should get the down event
4973 firstWindow->consumeMotionDown();
4974 secondWindow->assertNoEvents();
4975 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4976 wallpaper2->assertNoEvents();
4977
4978 // Transfer touch focus to the second window
4979 TransferFunction f = GetParam();
4980 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4981 ASSERT_TRUE(success);
4982
4983 // The first window gets cancel and the second gets down
4984 firstWindow->consumeMotionCancel();
4985 secondWindow->consumeMotionDown();
4986 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4987 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4988
4989 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004990 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4991 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004992 // The first window gets no events and the second gets up
4993 firstWindow->assertNoEvents();
4994 secondWindow->consumeMotionUp();
4995 wallpaper1->assertNoEvents();
4996 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4997}
4998
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004999// For the cases of single pointer touch and two pointers non-split touch, the api's
5000// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5001// for the case where there are multiple pointers split across several windows.
5002INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5003 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005004 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5005 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005006 return dispatcher->transferTouch(destChannelToken,
5007 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005008 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005009 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5010 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005011 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005012 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005013 }));
5014
Svet Ganov5d3bc372020-01-26 23:11:07 -08005015TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005017
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005018 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005019 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5020 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005021 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005022
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005023 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005024 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5025 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005026 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005027
5028 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005029 mDispatcher->onWindowInfosChanged(
5030 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005031
5032 PointF pointInFirst = {300, 200};
5033 PointF pointInSecond = {300, 600};
5034
5035 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005036 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5037 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5038 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005039 // Only the first window should get the down event
5040 firstWindow->consumeMotionDown();
5041 secondWindow->assertNoEvents();
5042
5043 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005044 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5045 ADISPLAY_ID_DEFAULT,
5046 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005047 // The first window gets a move and the second a down
5048 firstWindow->consumeMotionMove();
5049 secondWindow->consumeMotionDown();
5050
5051 // Transfer touch focus to the second window
5052 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5053 // The first window gets cancel and the new gets pointer down (it already saw down)
5054 firstWindow->consumeMotionCancel();
5055 secondWindow->consumeMotionPointerDown(1);
5056
5057 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005058 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5059 ADISPLAY_ID_DEFAULT,
5060 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005061 // The first window gets nothing and the second gets pointer up
5062 firstWindow->assertNoEvents();
5063 secondWindow->consumeMotionPointerUp(1);
5064
5065 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005066 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5067 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005068 // The first window gets nothing and the second gets up
5069 firstWindow->assertNoEvents();
5070 secondWindow->consumeMotionUp();
5071}
5072
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005073// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5074// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5075// touch is not supported, so the touch should continue on those windows and the transferred-to
5076// window should get nothing.
5077TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5079
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005080 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005081 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5082 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005083 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005084
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005085 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005086 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5087 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005088 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005089
5090 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005091 mDispatcher->onWindowInfosChanged(
5092 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005093
5094 PointF pointInFirst = {300, 200};
5095 PointF pointInSecond = {300, 600};
5096
5097 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005098 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5099 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5100 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005101 // Only the first window should get the down event
5102 firstWindow->consumeMotionDown();
5103 secondWindow->assertNoEvents();
5104
5105 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005106 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5107 ADISPLAY_ID_DEFAULT,
5108 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005109 // The first window gets a move and the second a down
5110 firstWindow->consumeMotionMove();
5111 secondWindow->consumeMotionDown();
5112
5113 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005114 const bool transferred =
5115 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005116 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5117 ASSERT_FALSE(transferred);
5118 firstWindow->assertNoEvents();
5119 secondWindow->assertNoEvents();
5120
5121 // The rest of the dispatch should proceed as normal
5122 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005123 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5124 ADISPLAY_ID_DEFAULT,
5125 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005126 // The first window gets MOVE and the second gets pointer up
5127 firstWindow->consumeMotionMove();
5128 secondWindow->consumeMotionUp();
5129
5130 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005131 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5132 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005133 // The first window gets nothing and the second gets up
5134 firstWindow->consumeMotionUp();
5135 secondWindow->assertNoEvents();
5136}
5137
Arthur Hungabbb9d82021-09-01 14:52:30 +00005138// This case will create two windows and one mirrored window on the default display and mirror
5139// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5140// the windows info of second display before default display.
5141TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5142 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5143 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005144 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005145 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005146 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005147 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005148 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005149
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005150 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005151 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005152
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005153 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005154 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005155
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005156 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005157 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005158
5159 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005160 mDispatcher->onWindowInfosChanged(
5161 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5162 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5163 *secondWindowInPrimary->getInfo()},
5164 {},
5165 0,
5166 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005167
5168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005169 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005170 {50, 50}))
5171 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5172
5173 // Window should receive motion event.
5174 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5175
5176 // Transfer touch focus
5177 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5178 secondWindowInPrimary->getToken()));
5179 // The first window gets cancel.
5180 firstWindowInPrimary->consumeMotionCancel();
5181 secondWindowInPrimary->consumeMotionDown();
5182
5183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005184 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005185 ADISPLAY_ID_DEFAULT, {150, 50}))
5186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5187 firstWindowInPrimary->assertNoEvents();
5188 secondWindowInPrimary->consumeMotionMove();
5189
5190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005191 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005192 {150, 50}))
5193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5194 firstWindowInPrimary->assertNoEvents();
5195 secondWindowInPrimary->consumeMotionUp();
5196}
5197
5198// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5199// 'transferTouch' api.
5200TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5201 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5202 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005203 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005204 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005205 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005206 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005207 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005208
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005209 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005210 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005211
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005212 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005213 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005214
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005215 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005216 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005217
5218 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005219 mDispatcher->onWindowInfosChanged(
5220 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5221 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5222 *secondWindowInPrimary->getInfo()},
5223 {},
5224 0,
5225 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005226
5227 // Touch on second display.
5228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005229 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5230 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005231 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5232
5233 // Window should receive motion event.
5234 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5235
5236 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005237 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005238
5239 // The first window gets cancel.
5240 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5241 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5242
5243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005244 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005245 SECOND_DISPLAY_ID, {150, 50}))
5246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5247 firstWindowInPrimary->assertNoEvents();
5248 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5249
5250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005251 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005252 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5253 firstWindowInPrimary->assertNoEvents();
5254 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5255}
5256
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005257TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005259 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5260 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005261
Vishnu Nair47074b82020-08-14 11:54:47 -07005262 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005263 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005264 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005265
5266 window->consumeFocusEvent(true);
5267
Prabir Pradhan678438e2023-04-13 19:32:51 +00005268 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005269
5270 // Window should receive key down event.
5271 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005272
5273 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005274 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005275 mFakePolicy->assertUserActivityPoked();
5276}
5277
5278TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5280 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5281 "Fake Window", ADISPLAY_ID_DEFAULT);
5282
5283 window->setDisableUserActivity(true);
5284 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005285 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005286 setFocusedWindow(window);
5287
5288 window->consumeFocusEvent(true);
5289
5290 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5291
5292 // Window should receive key down event.
5293 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5294
5295 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005296 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005297 mFakePolicy->assertUserActivityNotPoked();
5298}
5299
5300TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5302 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5303 "Fake Window", ADISPLAY_ID_DEFAULT);
5304
5305 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005306 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005307 setFocusedWindow(window);
5308
5309 window->consumeFocusEvent(true);
5310
5311 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5312 mDispatcher->waitForIdle();
5313
5314 // System key is not passed down
5315 window->assertNoEvents();
5316
5317 // Should have poked user activity
5318 mFakePolicy->assertUserActivityPoked();
5319}
5320
5321TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5322 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5323 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5324 "Fake Window", ADISPLAY_ID_DEFAULT);
5325
5326 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005327 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005328 setFocusedWindow(window);
5329
5330 window->consumeFocusEvent(true);
5331
5332 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5333 mDispatcher->waitForIdle();
5334
5335 // System key is not passed down
5336 window->assertNoEvents();
5337
5338 // Should have poked user activity
5339 mFakePolicy->assertUserActivityPoked();
5340}
5341
5342TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5344 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5345 "Fake Window", ADISPLAY_ID_DEFAULT);
5346
5347 window->setDisableUserActivity(true);
5348 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005349 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005350 setFocusedWindow(window);
5351
5352 window->consumeFocusEvent(true);
5353
5354 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5355 mDispatcher->waitForIdle();
5356
5357 // System key is not passed down
5358 window->assertNoEvents();
5359
5360 // Should have poked user activity
5361 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005362}
5363
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005364TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5366 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5367 "Fake Window", ADISPLAY_ID_DEFAULT);
5368
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005369 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005370
5371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005372 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005373 ADISPLAY_ID_DEFAULT, {100, 100}))
5374 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5375
5376 window->consumeMotionEvent(
5377 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5378
5379 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005380 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005381 mFakePolicy->assertUserActivityPoked();
5382}
5383
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005384TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005386 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5387 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005388
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005389 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005390
Prabir Pradhan678438e2023-04-13 19:32:51 +00005391 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005392 mDispatcher->waitForIdle();
5393
5394 window->assertNoEvents();
5395}
5396
5397// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5398TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005399 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005400 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5401 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005402
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005403 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005404
5405 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005406 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005407 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5409 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005410
5411 // Window should receive only the motion event
5412 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5413 window->assertNoEvents(); // Key event or focus event will not be received
5414}
5415
arthurhungea3f4fc2020-12-21 23:18:53 +08005416TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5417 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5418
arthurhungea3f4fc2020-12-21 23:18:53 +08005419 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005420 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5421 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005422 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005423
arthurhungea3f4fc2020-12-21 23:18:53 +08005424 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005425 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5426 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005427 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005428
5429 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005430 mDispatcher->onWindowInfosChanged(
5431 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005432
5433 PointF pointInFirst = {300, 200};
5434 PointF pointInSecond = {300, 600};
5435
5436 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005437 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5438 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5439 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005440 // Only the first window should get the down event
5441 firstWindow->consumeMotionDown();
5442 secondWindow->assertNoEvents();
5443
5444 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005445 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5446 ADISPLAY_ID_DEFAULT,
5447 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005448 // The first window gets a move and the second a down
5449 firstWindow->consumeMotionMove();
5450 secondWindow->consumeMotionDown();
5451
5452 // Send pointer cancel to the second window
5453 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005454 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005455 {pointInFirst, pointInSecond});
5456 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005457 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005458 // The first window gets move and the second gets cancel.
5459 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5460 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5461
5462 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005463 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5464 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005465 // The first window gets up and the second gets nothing.
5466 firstWindow->consumeMotionUp();
5467 secondWindow->assertNoEvents();
5468}
5469
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005470TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5472
5473 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005476 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5477 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5478 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5479
Harry Cutts33476232023-01-30 19:57:29 +00005480 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005481 window->assertNoEvents();
5482 mDispatcher->waitForIdle();
5483}
5484
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005485using InputDispatcherMonitorTest = InputDispatcherTest;
5486
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005487/**
5488 * Two entities that receive touch: A window, and a global monitor.
5489 * The touch goes to the window, and then the window disappears.
5490 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5491 * for the monitor, as well.
5492 * 1. foregroundWindow
5493 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5494 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005495TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005496 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5497 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005498 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005499
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005500 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005501
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005502 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005504 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005505 {100, 200}))
5506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5507
5508 // Both the foreground window and the global monitor should receive the touch down
5509 window->consumeMotionDown();
5510 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5511
5512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005513 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005514 ADISPLAY_ID_DEFAULT, {110, 200}))
5515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5516
5517 window->consumeMotionMove();
5518 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5519
5520 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005521 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005522 window->consumeMotionCancel();
5523 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5524
5525 // If more events come in, there will be no more foreground window to send them to. This will
5526 // cause a cancel for the monitor, as well.
5527 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005528 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005529 ADISPLAY_ID_DEFAULT, {120, 200}))
5530 << "Injection should fail because the window was removed";
5531 window->assertNoEvents();
5532 // Global monitor now gets the cancel
5533 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5534}
5535
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005536TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005537 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005538 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5539 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005540 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005541
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005542 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005543
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005545 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005547 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005548 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005549}
5550
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005551TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5552 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005553
Chris Yea209fde2020-07-22 13:54:51 -07005554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005555 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5556 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005557 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005558
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005560 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005562 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005563 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005564
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005565 // Pilfer pointers from the monitor.
5566 // This should not do anything and the window should continue to receive events.
5567 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005568
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005570 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005571 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005572 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005573
5574 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5575 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005576}
5577
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005578TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005580 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5581 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005582 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005583 window->setWindowOffset(20, 40);
5584 window->setWindowTransform(0, 1, -1, 0);
5585
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005586 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005587
5588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005589 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5591 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5592 MotionEvent* event = monitor.consumeMotion();
5593 // Even though window has transform, gesture monitor must not.
5594 ASSERT_EQ(ui::Transform(), event->getTransform());
5595}
5596
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005597TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005599 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005600
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005601 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005602 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005603 << "Injection should fail if there is a monitor, but no touchable window";
5604 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005605}
5606
chaviw81e2bb92019-12-18 15:03:51 -08005607TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005608 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005609 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5610 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005611
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005612 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005613
5614 NotifyMotionArgs motionArgs =
5615 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5616 ADISPLAY_ID_DEFAULT);
5617
Prabir Pradhan678438e2023-04-13 19:32:51 +00005618 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005619 // Window should receive motion down event.
5620 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5621
5622 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005623 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005624 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5625 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5626 motionArgs.pointerCoords[0].getX() - 10);
5627
Prabir Pradhan678438e2023-04-13 19:32:51 +00005628 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005629 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005630 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005631}
5632
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005633/**
5634 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5635 * the device default right away. In the test scenario, we check both the default value,
5636 * and the action of enabling / disabling.
5637 */
5638TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005640 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5641 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005642 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005643
5644 // Set focused application.
5645 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005646 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005647
5648 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005650 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005651 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005652
5653 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005654 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005655 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005656 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005657
5658 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005659 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005660 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005661 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005662 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005663 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005664 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005665 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005666
5667 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005668 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005669 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005670 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005671
5672 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005673 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005674 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005675 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005676 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005678 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005679 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005680
5681 window->assertNoEvents();
5682}
5683
Gang Wange9087892020-01-07 12:17:14 -05005684TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5687 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005688
5689 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005690 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005691
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005693 setFocusedWindow(window);
5694
Harry Cutts33476232023-01-30 19:57:29 +00005695 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005696
Prabir Pradhan678438e2023-04-13 19:32:51 +00005697 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5698 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005699
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005700 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005701 ASSERT_NE(event, nullptr);
5702
5703 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5704 ASSERT_NE(verified, nullptr);
5705 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5706
5707 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5708 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5709 ASSERT_EQ(keyArgs.source, verified->source);
5710 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5711
5712 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5713
5714 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005715 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005716 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005717 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5718 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5719 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5720 ASSERT_EQ(0, verifiedKey.repeatCount);
5721}
5722
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005723TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005725 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5726 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005727
5728 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5729
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005730 ui::Transform transform;
5731 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5732
5733 gui::DisplayInfo displayInfo;
5734 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5735 displayInfo.transform = transform;
5736
Patrick Williamsd828f302023-04-28 17:52:08 -05005737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005738
Prabir Pradhan678438e2023-04-13 19:32:51 +00005739 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005740 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5741 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005742 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005743
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005744 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005745 ASSERT_NE(event, nullptr);
5746
5747 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5748 ASSERT_NE(verified, nullptr);
5749 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5750
5751 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5752 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5753 EXPECT_EQ(motionArgs.source, verified->source);
5754 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5755
5756 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5757
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005758 const vec2 rawXY =
5759 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5760 motionArgs.pointerCoords[0].getXYValue());
5761 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5762 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005763 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005764 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005765 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005766 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5767 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5768}
5769
chaviw09c8d2d2020-08-24 15:48:26 -07005770/**
5771 * Ensure that separate calls to sign the same data are generating the same key.
5772 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5773 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5774 * tests.
5775 */
5776TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5777 KeyEvent event = getTestKeyEvent();
5778 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5779
5780 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5781 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5782 ASSERT_EQ(hmac1, hmac2);
5783}
5784
5785/**
5786 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5787 */
5788TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5789 KeyEvent event = getTestKeyEvent();
5790 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5791 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5792
5793 verifiedEvent.deviceId += 1;
5794 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5795
5796 verifiedEvent.source += 1;
5797 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5798
5799 verifiedEvent.eventTimeNanos += 1;
5800 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5801
5802 verifiedEvent.displayId += 1;
5803 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5804
5805 verifiedEvent.action += 1;
5806 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5807
5808 verifiedEvent.downTimeNanos += 1;
5809 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5810
5811 verifiedEvent.flags += 1;
5812 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5813
5814 verifiedEvent.keyCode += 1;
5815 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5816
5817 verifiedEvent.scanCode += 1;
5818 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5819
5820 verifiedEvent.metaState += 1;
5821 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5822
5823 verifiedEvent.repeatCount += 1;
5824 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5825}
5826
Vishnu Nair958da932020-08-21 17:12:37 -07005827TEST_F(InputDispatcherTest, SetFocusedWindow) {
5828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5829 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005830 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005831 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005832 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005833 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5834
5835 // Top window is also focusable but is not granted focus.
5836 windowTop->setFocusable(true);
5837 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005838 mDispatcher->onWindowInfosChanged(
5839 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005840 setFocusedWindow(windowSecond);
5841
5842 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005844 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005845
5846 // Focused window should receive event.
5847 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5848 windowTop->assertNoEvents();
5849}
5850
5851TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5853 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005854 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005855 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5856
5857 window->setFocusable(true);
5858 // Release channel for window is no longer valid.
5859 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005860 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005861 setFocusedWindow(window);
5862
5863 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005864 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005865
5866 // window channel is invalid, so it should not receive any input event.
5867 window->assertNoEvents();
5868}
5869
5870TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5871 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5872 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005873 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005874 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005875 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005878 setFocusedWindow(window);
5879
5880 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005881 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005882
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005883 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005884 window->assertNoEvents();
5885}
5886
5887TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5889 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005890 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005891 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005892 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005893 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5894
5895 windowTop->setFocusable(true);
5896 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005897 mDispatcher->onWindowInfosChanged(
5898 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005899 setFocusedWindow(windowTop);
5900 windowTop->consumeFocusEvent(true);
5901
Chavi Weingarten847e8512023-03-29 00:26:09 +00005902 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005903 mDispatcher->onWindowInfosChanged(
5904 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005905 windowSecond->consumeFocusEvent(true);
5906 windowTop->consumeFocusEvent(false);
5907
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005909 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005910
5911 // Focused window should receive event.
5912 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5913}
5914
Chavi Weingarten847e8512023-03-29 00:26:09 +00005915TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5917 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005918 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005919 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005920 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005921 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5922
5923 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005924 windowSecond->setFocusable(false);
5925 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005926 mDispatcher->onWindowInfosChanged(
5927 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005928 setFocusedWindow(windowTop);
5929 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005930
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005932 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005933
5934 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005935 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005936 windowSecond->assertNoEvents();
5937}
5938
5939TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5940 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5941 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005942 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005943 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005944 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5945 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005946 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5947
5948 window->setFocusable(true);
5949 previousFocusedWindow->setFocusable(true);
5950 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005951 mDispatcher->onWindowInfosChanged(
5952 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005953 setFocusedWindow(previousFocusedWindow);
5954 previousFocusedWindow->consumeFocusEvent(true);
5955
5956 // Requesting focus on invisible window takes focus from currently focused window.
5957 setFocusedWindow(window);
5958 previousFocusedWindow->consumeFocusEvent(false);
5959
5960 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005962 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5963 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005964
5965 // Window does not get focus event or key down.
5966 window->assertNoEvents();
5967
5968 // Window becomes visible.
5969 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005970 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005971
5972 // Window receives focus event.
5973 window->consumeFocusEvent(true);
5974 // Focused window receives key down.
5975 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5976}
5977
Vishnu Nair599f1412021-06-21 10:39:58 -07005978TEST_F(InputDispatcherTest, DisplayRemoved) {
5979 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5980 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005981 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005982 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5983
5984 // window is granted focus.
5985 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005986 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005987 setFocusedWindow(window);
5988 window->consumeFocusEvent(true);
5989
5990 // When a display is removed window loses focus.
5991 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5992 window->consumeFocusEvent(false);
5993}
5994
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005995/**
5996 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5997 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5998 * of the 'slipperyEnterWindow'.
5999 *
6000 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6001 * a way so that the touched location is no longer covered by the top window.
6002 *
6003 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6004 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6005 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6006 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6007 * with ACTION_DOWN).
6008 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6009 * window moved itself away from the touched location and had Flag::SLIPPERY.
6010 *
6011 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6012 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6013 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6014 *
6015 * In this test, we ensure that the event received by the bottom window has
6016 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6017 */
6018TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006019 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006020 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006021
6022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6023 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6024
6025 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006026 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006027 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006028 // Make sure this one overlaps the bottom window
6029 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6030 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6031 // one. Windows with the same owner are not considered to be occluding each other.
6032 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6033
6034 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006035 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006036 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6037
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006038 mDispatcher->onWindowInfosChanged(
6039 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006040
6041 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006042 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6043 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6044 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006045 slipperyExitWindow->consumeMotionDown();
6046 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006047 mDispatcher->onWindowInfosChanged(
6048 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006049
Prabir Pradhan678438e2023-04-13 19:32:51 +00006050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6051 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6052 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006053
6054 slipperyExitWindow->consumeMotionCancel();
6055
6056 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6057 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6058}
6059
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006060/**
6061 * Two windows, one on the left and another on the right. The left window is slippery. The right
6062 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6063 * touch moves from the left window into the right window, the gesture should continue to go to the
6064 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6065 * reproduces a crash.
6066 */
6067TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6069
6070 sp<FakeWindowHandle> leftSlipperyWindow =
6071 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6072 leftSlipperyWindow->setSlippery(true);
6073 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6074
6075 sp<FakeWindowHandle> rightDropTouchesWindow =
6076 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6077 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6078 rightDropTouchesWindow->setDropInput(true);
6079
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006080 mDispatcher->onWindowInfosChanged(
6081 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006082
6083 // Start touch in the left window
6084 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6085 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6086 .build());
6087 leftSlipperyWindow->consumeMotionDown();
6088
6089 // And move it into the right window
6090 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6091 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6092 .build());
6093
6094 // Since the right window isn't eligible to receive input, touch does not slip.
6095 // The left window continues to receive the gesture.
6096 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6097 rightDropTouchesWindow->assertNoEvents();
6098}
6099
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006100/**
6101 * A single window is on screen first. Touch is injected into that window. Next, a second window
6102 * appears. Since the first window is slippery, touch will move from the first window to the second.
6103 */
6104TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6105 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6106 sp<FakeWindowHandle> originalWindow =
6107 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6108 originalWindow->setFrame(Rect(0, 0, 200, 200));
6109 originalWindow->setSlippery(true);
6110
6111 sp<FakeWindowHandle> appearingWindow =
6112 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6113 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6114
6115 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6116
6117 // Touch down on the original window
6118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6119 injectMotionEvent(*mDispatcher,
6120 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6121 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6122 .build()));
6123 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6124
6125 // Now, a new window appears. This could be, for example, a notification shade that appears
6126 // after user starts to drag down on the launcher window.
6127 mDispatcher->onWindowInfosChanged(
6128 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6130 injectMotionEvent(*mDispatcher,
6131 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6132 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6133 .build()));
6134 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6135 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6137 injectMotionEvent(*mDispatcher,
6138 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6139 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6140 .build()));
6141 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6142
6143 originalWindow->assertNoEvents();
6144 appearingWindow->assertNoEvents();
6145}
6146
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006147TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006148 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6150
6151 sp<FakeWindowHandle> leftWindow =
6152 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6153 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006154 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006155
6156 sp<FakeWindowHandle> rightSpy =
6157 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6158 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006159 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006160 rightSpy->setSpy(true);
6161 rightSpy->setTrustedOverlay(true);
6162
6163 sp<FakeWindowHandle> rightWindow =
6164 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6165 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006166 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006167
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006168 mDispatcher->onWindowInfosChanged(
6169 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006170
6171 // Touch in the left window
6172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6173 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6174 .build());
6175 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6176 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006177 ASSERT_NO_FATAL_FAILURE(
6178 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006179
6180 // Touch another finger over the right windows
6181 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6182 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6183 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6184 .build());
6185 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6186 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6187 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6188 mDispatcher->waitForIdle();
6189 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006190 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6191 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006192
6193 // Release finger over left window. The UP actions are not treated as device interaction.
6194 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6195 // is part of the UP action, we do not treat this as device interaction.
6196 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6197 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6198 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6199 .build());
6200 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6201 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6202 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6203 mDispatcher->waitForIdle();
6204 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6205
6206 // Move remaining finger
6207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6208 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6209 .build());
6210 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6211 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6212 mDispatcher->waitForIdle();
6213 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006214 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006215
6216 // Release all fingers
6217 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6218 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6219 .build());
6220 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6221 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6222 mDispatcher->waitForIdle();
6223 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6224}
6225
6226TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6227 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6228
6229 sp<FakeWindowHandle> window =
6230 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6231 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006232 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006233
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006234 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006235 setFocusedWindow(window);
6236 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6237
6238 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6239 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6240 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006241 ASSERT_NO_FATAL_FAILURE(
6242 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006243
6244 // The UP actions are not treated as device interaction.
6245 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6246 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6247 mDispatcher->waitForIdle();
6248 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6249}
6250
Garfield Tan1c7bc862020-01-28 13:24:04 -08006251class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6252protected:
6253 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6254 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6255
Chris Yea209fde2020-07-22 13:54:51 -07006256 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006257 sp<FakeWindowHandle> mWindow;
6258
6259 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006260 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006261 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006262 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006263 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006264 ASSERT_EQ(OK, mDispatcher->start());
6265
6266 setUpWindow();
6267 }
6268
6269 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006270 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006271 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006272
Vishnu Nair47074b82020-08-14 11:54:47 -07006273 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006274 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006275 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006276 mWindow->consumeFocusEvent(true);
6277 }
6278
Chris Ye2ad95392020-09-01 13:44:44 -07006279 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006280 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006281 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006282 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006283 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006284
6285 // Window should receive key down event.
6286 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6287 }
6288
6289 void expectKeyRepeatOnce(int32_t repeatCount) {
6290 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006291 mWindow->consumeKeyEvent(
6292 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006293 }
6294
Chris Ye2ad95392020-09-01 13:44:44 -07006295 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006296 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006297 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006298 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006299 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006300
6301 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006302 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006303 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006304 }
6305};
6306
6307TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006308 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006309 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6310 expectKeyRepeatOnce(repeatCount);
6311 }
6312}
6313
6314TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006315 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006316 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6317 expectKeyRepeatOnce(repeatCount);
6318 }
Harry Cutts33476232023-01-30 19:57:29 +00006319 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006320 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006321 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6322 expectKeyRepeatOnce(repeatCount);
6323 }
6324}
6325
6326TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006327 sendAndConsumeKeyDown(/*deviceId=*/1);
6328 expectKeyRepeatOnce(/*repeatCount=*/1);
6329 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006330 mWindow->assertNoEvents();
6331}
6332
6333TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006334 sendAndConsumeKeyDown(/*deviceId=*/1);
6335 expectKeyRepeatOnce(/*repeatCount=*/1);
6336 sendAndConsumeKeyDown(/*deviceId=*/2);
6337 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006338 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006339 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006340 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006341 expectKeyRepeatOnce(/*repeatCount=*/2);
6342 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006343 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006344 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006345 mWindow->assertNoEvents();
6346}
6347
6348TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006349 sendAndConsumeKeyDown(/*deviceId=*/1);
6350 expectKeyRepeatOnce(/*repeatCount=*/1);
6351 sendAndConsumeKeyDown(/*deviceId=*/2);
6352 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006353 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006354 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006355 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006356 mWindow->assertNoEvents();
6357}
6358
liushenxiang42232912021-05-21 20:24:09 +08006359TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6360 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006361 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006362 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006363 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6364 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6365 mWindow->assertNoEvents();
6366}
6367
Garfield Tan1c7bc862020-01-28 13:24:04 -08006368TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006369 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006370 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006371 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006372 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006373 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6374 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6375 IdGenerator::getSource(repeatEvent->getId()));
6376 }
6377}
6378
6379TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006380 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006381 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006382
6383 std::unordered_set<int32_t> idSet;
6384 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006385 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006386 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6387 int32_t id = repeatEvent->getId();
6388 EXPECT_EQ(idSet.end(), idSet.find(id));
6389 idSet.insert(id);
6390 }
6391}
6392
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006393/* Test InputDispatcher for MultiDisplay */
6394class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6395public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006396 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006397 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006398
Chris Yea209fde2020-07-22 13:54:51 -07006399 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006400 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006401 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006402
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006403 // Set focus window for primary display, but focused display would be second one.
6404 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006405 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006406 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6407
Vishnu Nair958da932020-08-21 17:12:37 -07006408 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006409 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006410
Chris Yea209fde2020-07-22 13:54:51 -07006411 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006412 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006413 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006414 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006415 // Set focus display to second one.
6416 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6417 // Set focus window for second display.
6418 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006419 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006420 mDispatcher->onWindowInfosChanged(
6421 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006422 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006423 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006424 }
6425
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006426 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006427 InputDispatcherTest::TearDown();
6428
Chris Yea209fde2020-07-22 13:54:51 -07006429 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006430 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006431 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006432 windowInSecondary.clear();
6433 }
6434
6435protected:
Chris Yea209fde2020-07-22 13:54:51 -07006436 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006437 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006438 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006439 sp<FakeWindowHandle> windowInSecondary;
6440};
6441
6442TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6443 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006445 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006446 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006447 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006448 windowInSecondary->assertNoEvents();
6449
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006450 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006452 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006454 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006455 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006456}
6457
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006458TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006459 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006461 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006462 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006463 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006464 windowInSecondary->assertNoEvents();
6465
6466 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006468 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006469 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006470 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006471
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006472 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006473 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006474
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006475 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006476 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006477 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006478
6479 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006480 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006481 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006482 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006483 windowInSecondary->assertNoEvents();
6484}
6485
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006486// Test per-display input monitors for motion event.
6487TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006488 FakeMonitorReceiver monitorInPrimary =
6489 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6490 FakeMonitorReceiver monitorInSecondary =
6491 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006492
6493 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006495 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006497 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006498 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006499 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006500 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006501
6502 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006504 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006505 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006506 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006507 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006508 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006509 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006510
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006511 // Lift up the touch from the second display
6512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006513 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6515 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6516 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6517
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006518 // Test inject a non-pointer motion event.
6519 // If specific a display, it will dispatch to the focused window of particular display,
6520 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006522 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006524 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006525 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006526 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006527 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006528}
6529
6530// Test per-display input monitors for key event.
6531TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006532 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006533 FakeMonitorReceiver monitorInPrimary =
6534 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6535 FakeMonitorReceiver monitorInSecondary =
6536 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006537
6538 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006540 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006541 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006542 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006543 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006544 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006545}
6546
Vishnu Nair958da932020-08-21 17:12:37 -07006547TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6548 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006549 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006550 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006551 mDispatcher->onWindowInfosChanged(
6552 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6553 *windowInSecondary->getInfo()},
6554 {},
6555 0,
6556 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006557 setFocusedWindow(secondWindowInPrimary);
6558 windowInPrimary->consumeFocusEvent(false);
6559 secondWindowInPrimary->consumeFocusEvent(true);
6560
6561 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6563 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006564 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006565 windowInPrimary->assertNoEvents();
6566 windowInSecondary->assertNoEvents();
6567 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6568}
6569
Arthur Hungdfd528e2021-12-08 13:23:04 +00006570TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6571 FakeMonitorReceiver monitorInPrimary =
6572 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6573 FakeMonitorReceiver monitorInSecondary =
6574 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6575
6576 // Test touch down on primary display.
6577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006578 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6580 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6581 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6582
6583 // Test touch down on second display.
6584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006585 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006586 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6587 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6588 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6589
6590 // Trigger cancel touch.
6591 mDispatcher->cancelCurrentTouch();
6592 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6593 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6594 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6595 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6596
6597 // Test inject a move motion event, no window/monitor should receive the event.
6598 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006599 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006600 ADISPLAY_ID_DEFAULT, {110, 200}))
6601 << "Inject motion event should return InputEventInjectionResult::FAILED";
6602 windowInPrimary->assertNoEvents();
6603 monitorInPrimary.assertNoEvents();
6604
6605 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006606 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006607 SECOND_DISPLAY_ID, {110, 200}))
6608 << "Inject motion event should return InputEventInjectionResult::FAILED";
6609 windowInSecondary->assertNoEvents();
6610 monitorInSecondary.assertNoEvents();
6611}
6612
Jackal Guof9696682018-10-05 12:23:23 +08006613class InputFilterTest : public InputDispatcherTest {
6614protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006615 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6616 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006617 NotifyMotionArgs motionArgs;
6618
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006619 motionArgs =
6620 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006621 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006622 motionArgs =
6623 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006624 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006625 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006626 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006627 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006628 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006629 } else {
6630 mFakePolicy->assertFilterInputEventWasNotCalled();
6631 }
6632 }
6633
6634 void testNotifyKey(bool expectToBeFiltered) {
6635 NotifyKeyArgs keyArgs;
6636
6637 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006638 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006639 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006640 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006641 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006642
6643 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006644 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006645 } else {
6646 mFakePolicy->assertFilterInputEventWasNotCalled();
6647 }
6648 }
6649};
6650
6651// Test InputFilter for MotionEvent
6652TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6653 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006654 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6655 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006656
6657 // Enable InputFilter
6658 mDispatcher->setInputFilterEnabled(true);
6659 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006660 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6661 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006662
6663 // Disable InputFilter
6664 mDispatcher->setInputFilterEnabled(false);
6665 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006666 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6667 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006668}
6669
6670// Test InputFilter for KeyEvent
6671TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6672 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006673 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006674
6675 // Enable InputFilter
6676 mDispatcher->setInputFilterEnabled(true);
6677 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006678 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006679
6680 // Disable InputFilter
6681 mDispatcher->setInputFilterEnabled(false);
6682 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006683 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006684}
6685
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006686// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6687// logical display coordinate space.
6688TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6689 ui::Transform firstDisplayTransform;
6690 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6691 ui::Transform secondDisplayTransform;
6692 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6693
6694 std::vector<gui::DisplayInfo> displayInfos(2);
6695 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6696 displayInfos[0].transform = firstDisplayTransform;
6697 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6698 displayInfos[1].transform = secondDisplayTransform;
6699
Patrick Williamsd828f302023-04-28 17:52:08 -05006700 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006701
6702 // Enable InputFilter
6703 mDispatcher->setInputFilterEnabled(true);
6704
6705 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006706 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6707 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006708}
6709
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006710class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6711protected:
6712 virtual void SetUp() override {
6713 InputDispatcherTest::SetUp();
6714
6715 /**
6716 * We don't need to enable input filter to test the injected event policy, but we enabled it
6717 * here to make the tests more realistic, since this policy only matters when inputfilter is
6718 * on.
6719 */
6720 mDispatcher->setInputFilterEnabled(true);
6721
6722 std::shared_ptr<InputApplicationHandle> application =
6723 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006724 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6725 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006726
6727 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6728 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006729 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006730 setFocusedWindow(mWindow);
6731 mWindow->consumeFocusEvent(true);
6732 }
6733
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006734 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6735 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006736 KeyEvent event;
6737
6738 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6739 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6740 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006741 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006742 const int32_t additionalPolicyFlags =
6743 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006745 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006746 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006747 policyFlags | additionalPolicyFlags));
6748
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006749 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006750 }
6751
6752 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6753 int32_t flags) {
6754 MotionEvent event;
6755 PointerProperties pointerProperties[1];
6756 PointerCoords pointerCoords[1];
6757 pointerProperties[0].clear();
6758 pointerProperties[0].id = 0;
6759 pointerCoords[0].clear();
6760 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6761 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6762
6763 ui::Transform identityTransform;
6764 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6765 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6766 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6767 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6768 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006769 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006770 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006771 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006772
6773 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006776 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006777 policyFlags | additionalPolicyFlags));
6778
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006779 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006780 }
6781
6782private:
6783 sp<FakeWindowHandle> mWindow;
6784};
6785
6786TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006787 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6788 // filter. Without it, the event will no different from a regularly injected event, and the
6789 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006790 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6791 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006792}
6793
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006794TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006795 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006796 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006797 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6798}
6799
6800TEST_F(InputFilterInjectionPolicyTest,
6801 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6802 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006803 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006804 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006805}
6806
6807TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006808 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6809 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006810}
6811
chaviwfd6d3512019-03-25 13:23:49 -07006812class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006813 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006814 InputDispatcherTest::SetUp();
6815
Chris Yea209fde2020-07-22 13:54:51 -07006816 std::shared_ptr<FakeApplicationHandle> application =
6817 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006818 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006819 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006820 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006821
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006822 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006823 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006824 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006825
6826 // Set focused application.
6827 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006828 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006829
6830 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006831 mDispatcher->onWindowInfosChanged(
6832 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006833 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006834 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006835 }
6836
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006837 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006838 InputDispatcherTest::TearDown();
6839
6840 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006841 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006842 }
6843
6844protected:
6845 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006846 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006847 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006848};
6849
6850// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6851// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6852// the onPointerDownOutsideFocus callback.
6853TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006855 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006856 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006858 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006859
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006860 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006861 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6862}
6863
6864// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6865// DOWN on the window that doesn't have focus. Ensure no window received the
6866// onPointerDownOutsideFocus callback.
6867TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6870 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006872 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006873
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006874 ASSERT_TRUE(mDispatcher->waitForIdle());
6875 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006876}
6877
6878// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6879// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6880TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006882 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006883 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006884 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006885
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006886 ASSERT_TRUE(mDispatcher->waitForIdle());
6887 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006888}
6889
6890// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6891// DOWN on the window that already has focus. Ensure no window received the
6892// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006893TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006895 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006896 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006898 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006899
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006900 ASSERT_TRUE(mDispatcher->waitForIdle());
6901 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006902}
6903
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006904// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6905// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6906TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6907 const MotionEvent event =
6908 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6909 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006910 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006911 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6912 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6915 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6916
6917 ASSERT_TRUE(mDispatcher->waitForIdle());
6918 mFakePolicy->assertOnPointerDownWasNotCalled();
6919 // Ensure that the unfocused window did not receive any FOCUS events.
6920 mUnfocusedWindow->assertNoEvents();
6921}
6922
chaviwaf87b3e2019-10-01 16:59:28 -07006923// These tests ensures we can send touch events to a single client when there are multiple input
6924// windows that point to the same client token.
6925class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6926 virtual void SetUp() override {
6927 InputDispatcherTest::SetUp();
6928
Chris Yea209fde2020-07-22 13:54:51 -07006929 std::shared_ptr<FakeApplicationHandle> application =
6930 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006931 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6932 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006933 mWindow1->setFrame(Rect(0, 0, 100, 100));
6934
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006935 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6936 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006937 mWindow2->setFrame(Rect(100, 100, 200, 200));
6938
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006939 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006940 }
6941
6942protected:
6943 sp<FakeWindowHandle> mWindow1;
6944 sp<FakeWindowHandle> mWindow2;
6945
6946 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006947 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006948 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6949 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006950 }
6951
6952 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6953 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006954 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006955 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006956
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006957 ASSERT_NE(nullptr, motionEvent)
6958 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006959
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006960 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006961 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006962
6963 for (size_t i = 0; i < points.size(); i++) {
6964 float expectedX = points[i].x;
6965 float expectedY = points[i].y;
6966
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006967 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006968 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006969 << ", got " << motionEvent->getX(i);
6970 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006971 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006972 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006973 }
6974 }
chaviw9eaa22c2020-07-01 16:21:27 -07006975
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006976 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006977 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006978 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6979 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006980
6981 // Always consume from window1 since it's the window that has the InputReceiver
6982 consumeMotionEvent(mWindow1, action, expectedPoints);
6983 }
chaviwaf87b3e2019-10-01 16:59:28 -07006984};
6985
6986TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6987 // Touch Window 1
6988 PointF touchedPoint = {10, 10};
6989 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006990 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006991
6992 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006993 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006994
6995 // Touch Window 2
6996 touchedPoint = {150, 150};
6997 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006998 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006999}
7000
chaviw9eaa22c2020-07-01 16:21:27 -07007001TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7002 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007003 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007004 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007005
7006 // Touch Window 1
7007 PointF touchedPoint = {10, 10};
7008 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007009 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007010 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007011 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007012
7013 // Touch Window 2
7014 touchedPoint = {150, 150};
7015 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007016 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7017 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007018
chaviw9eaa22c2020-07-01 16:21:27 -07007019 // Update the transform so rotation is set
7020 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007021 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007022 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7023 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007024}
7025
chaviw9eaa22c2020-07-01 16:21:27 -07007026TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007027 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007028 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007029
7030 // Touch Window 1
7031 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7032 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007033 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007034
7035 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007036 touchedPoints.push_back(PointF{150, 150});
7037 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007038 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007039
chaviw9eaa22c2020-07-01 16:21:27 -07007040 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007041 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007042 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007043
chaviw9eaa22c2020-07-01 16:21:27 -07007044 // Update the transform so rotation is set for Window 2
7045 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007046 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007047 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007048 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007049}
7050
chaviw9eaa22c2020-07-01 16:21:27 -07007051TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007052 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007053 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007054
7055 // Touch Window 1
7056 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7057 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007058 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007059
7060 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007061 touchedPoints.push_back(PointF{150, 150});
7062 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007063
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007064 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007065
7066 // Move both windows
7067 touchedPoints = {{20, 20}, {175, 175}};
7068 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7069 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7070
chaviw9eaa22c2020-07-01 16:21:27 -07007071 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007072
chaviw9eaa22c2020-07-01 16:21:27 -07007073 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007074 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007075 expectedPoints.pop_back();
7076
7077 // Touch Window 2
7078 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007079 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007080 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007081 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007082
7083 // Move both windows
7084 touchedPoints = {{20, 20}, {175, 175}};
7085 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7086 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7087
7088 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007089}
7090
7091TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7092 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007093 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007094
7095 // Touch Window 1
7096 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7097 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007098 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007099
7100 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007101 touchedPoints.push_back(PointF{150, 150});
7102 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007103
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007104 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007105
7106 // Move both windows
7107 touchedPoints = {{20, 20}, {175, 175}};
7108 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7109 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7110
chaviw9eaa22c2020-07-01 16:21:27 -07007111 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007112}
7113
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007114/**
7115 * When one of the windows is slippery, the touch should not slip into the other window with the
7116 * same input channel.
7117 */
7118TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7119 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007120 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007121
7122 // Touch down in window 1
7123 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7124 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7125 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7126
7127 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7128 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7129 // getting generated.
7130 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7131 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7132
7133 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7134}
7135
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007136/**
7137 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7138 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7139 * that the pointer is hovering over may have a different transform.
7140 */
7141TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007142 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007143
7144 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007145 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7146 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7147 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007148 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7149 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007150 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007151 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7152 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7153 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007154 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7155 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7156 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7157}
7158
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007159class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7160 virtual void SetUp() override {
7161 InputDispatcherTest::SetUp();
7162
Chris Yea209fde2020-07-22 13:54:51 -07007163 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007164 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007165 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7166 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007167 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007168 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007169 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007170
7171 // Set focused application.
7172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7173
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007174 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007175 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007176 mWindow->consumeFocusEvent(true);
7177 }
7178
7179 virtual void TearDown() override {
7180 InputDispatcherTest::TearDown();
7181 mWindow.clear();
7182 }
7183
7184protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007185 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007186 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007187 sp<FakeWindowHandle> mWindow;
7188 static constexpr PointF WINDOW_LOCATION = {20, 20};
7189
7190 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007192 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007193 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007195 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007196 WINDOW_LOCATION));
7197 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007198
7199 sp<FakeWindowHandle> addSpyWindow() {
7200 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007201 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007202 spy->setTrustedOverlay(true);
7203 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007204 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007205 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007206 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007207 return spy;
7208 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007209};
7210
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007211// Send a tap and respond, which should not cause an ANR.
7212TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7213 tapOnWindow();
7214 mWindow->consumeMotionDown();
7215 mWindow->consumeMotionUp();
7216 ASSERT_TRUE(mDispatcher->waitForIdle());
7217 mFakePolicy->assertNotifyAnrWasNotCalled();
7218}
7219
7220// Send a regular key and respond, which should not cause an ANR.
7221TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007223 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7224 ASSERT_TRUE(mDispatcher->waitForIdle());
7225 mFakePolicy->assertNotifyAnrWasNotCalled();
7226}
7227
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007228TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7229 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007230 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007231 mWindow->consumeFocusEvent(false);
7232
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007233 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007234 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7235 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007236 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007238 // Key will not go to window because we have no focused window.
7239 // The 'no focused window' ANR timer should start instead.
7240
7241 // Now, the focused application goes away.
7242 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7243 // The key should get dropped and there should be no ANR.
7244
7245 ASSERT_TRUE(mDispatcher->waitForIdle());
7246 mFakePolicy->assertNotifyAnrWasNotCalled();
7247}
7248
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007249// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007250// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7251// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007252TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
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 Vishniakou4cb50ca2020-05-26 21:43:02 -07007255 WINDOW_LOCATION));
7256
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007257 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7258 ASSERT_TRUE(sequenceNum);
7259 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007260 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007261
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007262 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007263 mWindow->consumeMotionEvent(
7264 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007265 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007266 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007267}
7268
7269// Send a key to the app and have the app not respond right away.
7270TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7271 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007273 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7274 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007275 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007276 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007277 ASSERT_TRUE(mDispatcher->waitForIdle());
7278}
7279
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007280// We have a focused application, but no focused window
7281TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007282 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007283 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007284 mWindow->consumeFocusEvent(false);
7285
7286 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007288 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007289 WINDOW_LOCATION));
7290 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7291 mDispatcher->waitForIdle();
7292 mFakePolicy->assertNotifyAnrWasNotCalled();
7293
7294 // Once a focused event arrives, we get an ANR for this application
7295 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7296 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007297 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007298 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007299 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007300 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007301 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007302 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007303 ASSERT_TRUE(mDispatcher->waitForIdle());
7304}
7305
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007306/**
7307 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7308 * there will not be an ANR.
7309 */
7310TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7311 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007312 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007313 mWindow->consumeFocusEvent(false);
7314
7315 KeyEvent event;
7316 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7317 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7318
7319 // Define a valid key down event that is stale (too old).
7320 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007321 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007322 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007323
7324 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7325
7326 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007327 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007328 InputEventInjectionSync::WAIT_FOR_RESULT,
7329 INJECT_EVENT_TIMEOUT, policyFlags);
7330 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7331 << "Injection should fail because the event is stale";
7332
7333 ASSERT_TRUE(mDispatcher->waitForIdle());
7334 mFakePolicy->assertNotifyAnrWasNotCalled();
7335 mWindow->assertNoEvents();
7336}
7337
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007338// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007339// Make sure that we don't notify policy twice about the same ANR.
7340TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007341 const std::chrono::duration appTimeout = 400ms;
7342 mApplication->setDispatchingTimeout(appTimeout);
7343 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7344
Vishnu Nair47074b82020-08-14 11:54:47 -07007345 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007346 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007347 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007348
7349 // Once a focused event arrives, we get an ANR for this application
7350 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7351 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007352 const std::chrono::duration eventInjectionTimeout = 100ms;
7353 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007354 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007355 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007356 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7357 /*allowKeyRepeat=*/false);
7358 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7359 << "result=" << ftl::enum_string(result);
7360 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7361 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7362 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7363 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007364
Vishnu Naire4df8752022-09-08 09:17:55 -07007365 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007366 // ANR should not be raised again. It is up to policy to do that if it desires.
7367 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007368
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007369 // If we now get a focused window, the ANR should stop, but the policy handles that via
7370 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007371 ASSERT_TRUE(mDispatcher->waitForIdle());
7372}
7373
7374// We have a focused application, but no focused window
7375TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007376 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007377 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007378 mWindow->consumeFocusEvent(false);
7379
7380 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007381 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007382
Vishnu Naire4df8752022-09-08 09:17:55 -07007383 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7384 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007385
7386 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007387 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007388 ASSERT_TRUE(mDispatcher->waitForIdle());
7389 mWindow->assertNoEvents();
7390}
7391
7392/**
7393 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7394 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7395 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7396 * the ANR mechanism should still work.
7397 *
7398 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7399 * DOWN event, while not responding on the second one.
7400 */
7401TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7402 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007403 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007404 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7405 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7406 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007407 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007408
7409 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007410 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007411 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7412 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7413 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007414 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007415
7416 // We have now sent down and up. Let's consume first event and then ANR on the second.
7417 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7418 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007419 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007420}
7421
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007422// A spy window can receive an ANR
7423TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7424 sp<FakeWindowHandle> spy = addSpyWindow();
7425
7426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007427 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007428 WINDOW_LOCATION));
7429 mWindow->consumeMotionDown();
7430
7431 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7432 ASSERT_TRUE(sequenceNum);
7433 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007434 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007435
7436 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007437 spy->consumeMotionEvent(
7438 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007439 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007440 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007441}
7442
7443// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007444// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007445TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7446 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007449 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007450 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007452
7453 // Stuck on the ACTION_UP
7454 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007455 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007456
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007457 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007458 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007459 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7460 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007461
7462 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7463 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007464 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007465 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007466 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007467}
7468
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007469// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007470// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007471TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7472 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007473
7474 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007475 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7476 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007477
7478 mWindow->consumeMotionDown();
7479 // Stuck on the ACTION_UP
7480 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007481 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007482
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007483 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007484 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007485 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7486 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007487
7488 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7489 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007490 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007491 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007492 spy->assertNoEvents();
7493}
7494
7495TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007496 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007497
7498 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7499
7500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007501 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007502 WINDOW_LOCATION));
7503
7504 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7505 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7506 ASSERT_TRUE(consumeSeq);
7507
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007508 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7509 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007510
7511 monitor.finishEvent(*consumeSeq);
7512 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7513
7514 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007515 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007516}
7517
7518// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7519// process events, you don't get an anr. When the window later becomes unresponsive again, you
7520// get an ANR again.
7521// 1. tap -> block on ACTION_UP -> receive ANR
7522// 2. consume all pending events (= queue becomes healthy again)
7523// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7524TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7525 tapOnWindow();
7526
7527 mWindow->consumeMotionDown();
7528 // Block on ACTION_UP
7529 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007530 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007531 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7532 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007533 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007534 mWindow->assertNoEvents();
7535
7536 tapOnWindow();
7537 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007538 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007539 mWindow->consumeMotionUp();
7540
7541 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007542 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007543 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007544 mWindow->assertNoEvents();
7545}
7546
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007547// If a connection remains unresponsive for a while, make sure policy is only notified once about
7548// it.
7549TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007551 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007552 WINDOW_LOCATION));
7553
7554 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007555 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007556 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007557 // 'notifyConnectionUnresponsive' should only be called once per connection
7558 mFakePolicy->assertNotifyAnrWasNotCalled();
7559 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007560 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007561 mWindow->consumeMotionEvent(
7562 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007563 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007564 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007565 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007566 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007567}
7568
7569/**
7570 * 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 -07007571 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007572 *
7573 * Warning!!!
7574 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7575 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007576 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007577 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7578 *
7579 * If that value changes, this test should also change.
7580 */
7581TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7582 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007583 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007584
7585 tapOnWindow();
7586 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7587 ASSERT_TRUE(downSequenceNum);
7588 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7589 ASSERT_TRUE(upSequenceNum);
7590 // Don't finish the events yet, and send a key
7591 // Injection will "succeed" because we will eventually give up and send the key to the focused
7592 // window even if motions are still being processed. But because the injection timeout is short,
7593 // we will receive INJECTION_TIMED_OUT as the result.
7594
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007595 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007596 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7597 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007598 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007599 // Key will not be sent to the window, yet, because the window is still processing events
7600 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007601 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7602 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7603 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7604 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007605
7606 std::this_thread::sleep_for(500ms);
7607 // if we wait long enough though, dispatcher will give up, and still send the key
7608 // to the focused window, even though we have not yet finished the motion event
7609 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7610 mWindow->finishEvent(*downSequenceNum);
7611 mWindow->finishEvent(*upSequenceNum);
7612}
7613
7614/**
7615 * If a window is processing a motion event, and then a key event comes in, the key event should
7616 * not go to the focused window until the motion is processed.
7617 * If then a new motion comes in, then the pending key event should be going to the currently
7618 * focused window right away.
7619 */
7620TEST_F(InputDispatcherSingleWindowAnr,
7621 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7622 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007623 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007624
7625 tapOnWindow();
7626 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7627 ASSERT_TRUE(downSequenceNum);
7628 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7629 ASSERT_TRUE(upSequenceNum);
7630 // Don't finish the events yet, and send a key
7631 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007633 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7634 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007635 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007636 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7637 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7638 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7639 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007640
7641 // Now tap down again. It should cause the pending key to go to the focused window right away.
7642 tapOnWindow();
7643 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7644 // the other events yet. We can finish events in any order.
7645 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7646 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7647 mWindow->consumeMotionDown();
7648 mWindow->consumeMotionUp();
7649 mWindow->assertNoEvents();
7650}
7651
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007652/**
7653 * Send an event to the app and have the app not respond right away.
7654 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7655 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7656 * At some point, the window becomes responsive again.
7657 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7658 */
7659TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7661 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7662 .build());
7663
7664 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7665 ASSERT_TRUE(sequenceNum);
7666 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7667 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7668
7669 mWindow->finishEvent(*sequenceNum);
7670 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7671 ASSERT_TRUE(mDispatcher->waitForIdle());
7672 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7673
7674 // Now that the window is responsive, let's continue the gesture.
7675 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7676 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7677 .build());
7678
7679 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7680 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7681 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7682 .build());
7683
7684 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7685 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7686 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7687 .build());
7688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7689 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7690 .build());
7691 // We already canceled this pointer, so the window shouldn't get any new events.
7692 mWindow->assertNoEvents();
7693
7694 // Start another one.
7695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7696 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7697 .build());
7698 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7699}
7700
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007701class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7702 virtual void SetUp() override {
7703 InputDispatcherTest::SetUp();
7704
Chris Yea209fde2020-07-22 13:54:51 -07007705 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007706 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007707 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7708 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007709 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007710 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007711 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007712
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007713 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7714 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007715 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007716 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007717
7718 // Set focused application.
7719 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007720 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007721
7722 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007723 mDispatcher->onWindowInfosChanged(
7724 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007725 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007726 mFocusedWindow->consumeFocusEvent(true);
7727 }
7728
7729 virtual void TearDown() override {
7730 InputDispatcherTest::TearDown();
7731
7732 mUnfocusedWindow.clear();
7733 mFocusedWindow.clear();
7734 }
7735
7736protected:
Chris Yea209fde2020-07-22 13:54:51 -07007737 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007738 sp<FakeWindowHandle> mUnfocusedWindow;
7739 sp<FakeWindowHandle> mFocusedWindow;
7740 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7741 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7742 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7743
7744 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7745
7746 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7747
7748private:
7749 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007751 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007752 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007754 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007755 location));
7756 }
7757};
7758
7759// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7760// should be ANR'd first.
7761TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007763 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007764 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007766 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007767 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007768 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007769 // We consumed all events, so no ANR
7770 ASSERT_TRUE(mDispatcher->waitForIdle());
7771 mFakePolicy->assertNotifyAnrWasNotCalled();
7772
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007774 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007775 FOCUSED_WINDOW_LOCATION));
7776 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7777 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007778
7779 const std::chrono::duration timeout =
7780 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007781 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007782 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7783 // sequence to make it consistent
7784 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007785 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007786 mFocusedWindow->consumeMotionDown();
7787 // This cancel is generated because the connection was unresponsive
7788 mFocusedWindow->consumeMotionCancel();
7789 mFocusedWindow->assertNoEvents();
7790 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007791 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007792 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7793 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007794 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007795}
7796
7797// If we have 2 windows with identical timeouts that are both unresponsive,
7798// it doesn't matter which order they should have ANR.
7799// But we should receive ANR for both.
7800TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7801 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007802 mUnfocusedWindow->setDispatchingTimeout(
7803 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007804 mDispatcher->onWindowInfosChanged(
7805 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007806
7807 tapOnFocusedWindow();
7808 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007809 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007810 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7811 mFocusedWindow->getDispatchingTimeout(
7812 DISPATCHING_TIMEOUT)),
7813 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7814
7815 ASSERT_THAT(anrConnectionTokens,
7816 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7817 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007818
7819 ASSERT_TRUE(mDispatcher->waitForIdle());
7820 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007821
7822 mFocusedWindow->consumeMotionDown();
7823 mFocusedWindow->consumeMotionUp();
7824 mUnfocusedWindow->consumeMotionOutside();
7825
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007826 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7827 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007828
7829 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007830 ASSERT_THAT(responsiveTokens,
7831 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7832 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007833 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007834}
7835
7836// If a window is already not responding, the second tap on the same window should be ignored.
7837// We should also log an error to account for the dropped event (not tested here).
7838// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7839TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7840 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007841 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007842 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007843 // Receive the events, but don't respond
7844 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7845 ASSERT_TRUE(downEventSequenceNum);
7846 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7847 ASSERT_TRUE(upEventSequenceNum);
7848 const std::chrono::duration timeout =
7849 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007850 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007851
7852 // Tap once again
7853 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007854 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007855 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007856 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007857 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007858 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007859 FOCUSED_WINDOW_LOCATION));
7860 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7861 // valid touch target
7862 mUnfocusedWindow->assertNoEvents();
7863
7864 // Consume the first tap
7865 mFocusedWindow->finishEvent(*downEventSequenceNum);
7866 mFocusedWindow->finishEvent(*upEventSequenceNum);
7867 ASSERT_TRUE(mDispatcher->waitForIdle());
7868 // The second tap did not go to the focused window
7869 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007870 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007871 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7872 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007873 mFakePolicy->assertNotifyAnrWasNotCalled();
7874}
7875
7876// If you tap outside of all windows, there will not be ANR
7877TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007878 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007879 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007880 LOCATION_OUTSIDE_ALL_WINDOWS));
7881 ASSERT_TRUE(mDispatcher->waitForIdle());
7882 mFakePolicy->assertNotifyAnrWasNotCalled();
7883}
7884
7885// Since the focused window is paused, tapping on it should not produce any events
7886TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7887 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007888 mDispatcher->onWindowInfosChanged(
7889 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007890
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007891 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007892 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007893 FOCUSED_WINDOW_LOCATION));
7894
7895 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7896 ASSERT_TRUE(mDispatcher->waitForIdle());
7897 // Should not ANR because the window is paused, and touches shouldn't go to it
7898 mFakePolicy->assertNotifyAnrWasNotCalled();
7899
7900 mFocusedWindow->assertNoEvents();
7901 mUnfocusedWindow->assertNoEvents();
7902}
7903
7904/**
7905 * 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 -07007906 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007907 * If a different window becomes focused at this time, the key should go to that window instead.
7908 *
7909 * Warning!!!
7910 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7911 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007912 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007913 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7914 *
7915 * If that value changes, this test should also change.
7916 */
7917TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7918 // Set a long ANR timeout to prevent it from triggering
7919 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007920 mDispatcher->onWindowInfosChanged(
7921 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007922
7923 tapOnUnfocusedWindow();
7924 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7925 ASSERT_TRUE(downSequenceNum);
7926 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7927 ASSERT_TRUE(upSequenceNum);
7928 // Don't finish the events yet, and send a key
7929 // Injection will succeed because we will eventually give up and send the key to the focused
7930 // window even if motions are still being processed.
7931
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007932 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007933 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7934 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007937 // and the key remains pending, waiting for the touch events to be processed.
7938 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7939 // under the hood.
7940 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7941 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007942
7943 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007944 mFocusedWindow->setFocusable(false);
7945 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007946 mDispatcher->onWindowInfosChanged(
7947 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007948 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007949
7950 // Focus events should precede the key events
7951 mUnfocusedWindow->consumeFocusEvent(true);
7952 mFocusedWindow->consumeFocusEvent(false);
7953
7954 // Finish the tap events, which should unblock dispatcher
7955 mUnfocusedWindow->finishEvent(*downSequenceNum);
7956 mUnfocusedWindow->finishEvent(*upSequenceNum);
7957
7958 // Now that all queues are cleared and no backlog in the connections, the key event
7959 // can finally go to the newly focused "mUnfocusedWindow".
7960 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7961 mFocusedWindow->assertNoEvents();
7962 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007963 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007964}
7965
7966// When the touch stream is split across 2 windows, and one of them does not respond,
7967// then ANR should be raised and the touch should be canceled for the unresponsive window.
7968// The other window should not be affected by that.
7969TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7970 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007971 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7972 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7973 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007974 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007975 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007976
7977 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007978 mDispatcher->notifyMotion(
7979 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7980 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007981
7982 const std::chrono::duration timeout =
7983 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007984 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007985
7986 mUnfocusedWindow->consumeMotionDown();
7987 mFocusedWindow->consumeMotionDown();
7988 // Focused window may or may not receive ACTION_MOVE
7989 // But it should definitely receive ACTION_CANCEL due to the ANR
7990 InputEvent* event;
7991 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7992 ASSERT_TRUE(moveOrCancelSequenceNum);
7993 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7994 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007995 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007996 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7997 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7998 mFocusedWindow->consumeMotionCancel();
7999 } else {
8000 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8001 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008002 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008003 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8004 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008005
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008006 mUnfocusedWindow->assertNoEvents();
8007 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008008 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008009}
8010
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008011/**
8012 * If we have no focused window, and a key comes in, we start the ANR timer.
8013 * The focused application should add a focused window before the timer runs out to prevent ANR.
8014 *
8015 * If the user touches another application during this time, the key should be dropped.
8016 * Next, if a new focused window comes in, without toggling the focused application,
8017 * then no ANR should occur.
8018 *
8019 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8020 * but in some cases the policy may not update the focused application.
8021 */
8022TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8023 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8024 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008025 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008026 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8027 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8028 mFocusedWindow->setFocusable(false);
8029
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008030 mDispatcher->onWindowInfosChanged(
8031 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008032 mFocusedWindow->consumeFocusEvent(false);
8033
8034 // Send a key. The ANR timer should start because there is no focused window.
8035 // 'focusedApplication' will get blamed if this timer completes.
8036 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008037 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008038 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8039 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008040 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008042
8043 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8044 // then the injected touches won't cause the focused event to get dropped.
8045 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8046 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8047 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8048 // For this test, it means that the key would get delivered to the window once it becomes
8049 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008050 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008051
8052 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008053 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8054 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8055 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008056
8057 // We do not consume the motion right away, because that would require dispatcher to first
8058 // process (== drop) the key event, and by that time, ANR will be raised.
8059 // Set the focused window first.
8060 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008061 mDispatcher->onWindowInfosChanged(
8062 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008063 setFocusedWindow(mFocusedWindow);
8064 mFocusedWindow->consumeFocusEvent(true);
8065 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8066 // to another application. This could be a bug / behaviour in the policy.
8067
8068 mUnfocusedWindow->consumeMotionDown();
8069
8070 ASSERT_TRUE(mDispatcher->waitForIdle());
8071 // Should not ANR because we actually have a focused window. It was just added too slowly.
8072 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8073}
8074
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008075// These tests ensure we cannot send touch events to a window that's positioned behind a window
8076// that has feature NO_INPUT_CHANNEL.
8077// Layout:
8078// Top (closest to user)
8079// mNoInputWindow (above all windows)
8080// mBottomWindow
8081// Bottom (furthest from user)
8082class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8083 virtual void SetUp() override {
8084 InputDispatcherTest::SetUp();
8085
8086 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008087 mNoInputWindow =
8088 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8089 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008090 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008091 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008092 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8093 // It's perfectly valid for this window to not have an associated input channel
8094
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008095 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8096 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008097 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8098
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008099 mDispatcher->onWindowInfosChanged(
8100 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008101 }
8102
8103protected:
8104 std::shared_ptr<FakeApplicationHandle> mApplication;
8105 sp<FakeWindowHandle> mNoInputWindow;
8106 sp<FakeWindowHandle> mBottomWindow;
8107};
8108
8109TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8110 PointF touchedPoint = {10, 10};
8111
Prabir Pradhan678438e2023-04-13 19:32:51 +00008112 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8114 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008115
8116 mNoInputWindow->assertNoEvents();
8117 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8118 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8119 // and therefore should prevent mBottomWindow from receiving touches
8120 mBottomWindow->assertNoEvents();
8121}
8122
8123/**
8124 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8125 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8126 */
8127TEST_F(InputDispatcherMultiWindowOcclusionTests,
8128 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008129 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8130 "Window with input channel and NO_INPUT_CHANNEL",
8131 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008132
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008133 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008134 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008135 mDispatcher->onWindowInfosChanged(
8136 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008137
8138 PointF touchedPoint = {10, 10};
8139
Prabir Pradhan678438e2023-04-13 19:32:51 +00008140 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8141 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8142 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008143
8144 mNoInputWindow->assertNoEvents();
8145 mBottomWindow->assertNoEvents();
8146}
8147
Vishnu Nair958da932020-08-21 17:12:37 -07008148class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8149protected:
8150 std::shared_ptr<FakeApplicationHandle> mApp;
8151 sp<FakeWindowHandle> mWindow;
8152 sp<FakeWindowHandle> mMirror;
8153
8154 virtual void SetUp() override {
8155 InputDispatcherTest::SetUp();
8156 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008157 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8158 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8159 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008160 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8161 mWindow->setFocusable(true);
8162 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008163 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008164 }
8165};
8166
8167TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8168 // Request focus on a mirrored window
8169 setFocusedWindow(mMirror);
8170
8171 // window gets focused
8172 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008174 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008175 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8176}
8177
8178// A focused & mirrored window remains focused only if the window and its mirror are both
8179// focusable.
8180TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8181 setFocusedWindow(mMirror);
8182
8183 // window gets focused
8184 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008186 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008187 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008189 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008190 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8191
8192 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008193 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008194
8195 // window loses focus since one of the windows associated with the token in not focusable
8196 mWindow->consumeFocusEvent(false);
8197
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008198 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008199 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008200 mWindow->assertNoEvents();
8201}
8202
8203// A focused & mirrored window remains focused until the window and its mirror both become
8204// invisible.
8205TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
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 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008218 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *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 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008228 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008229
8230 // window loses focus only after all windows associated with the token become invisible.
8231 mWindow->consumeFocusEvent(false);
8232
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008233 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008234 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008235 mWindow->assertNoEvents();
8236}
8237
8238// A focused & mirrored window remains focused until both windows are removed.
8239TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8240 setFocusedWindow(mMirror);
8241
8242 // window gets focused
8243 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008245 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008246 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008248 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008249 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8250
8251 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008252 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008253
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008255 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008256 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008258 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008259 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8260
8261 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008262 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008263 mWindow->consumeFocusEvent(false);
8264
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008265 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008266 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008267 mWindow->assertNoEvents();
8268}
8269
8270// Focus request can be pending until one window becomes visible.
8271TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8272 // Request focus on an invisible mirror.
8273 mWindow->setVisible(false);
8274 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008275 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008276 setFocusedWindow(mMirror);
8277
8278 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008280 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8281 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008282
8283 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008284 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008285
8286 // window gets focused
8287 mWindow->consumeFocusEvent(true);
8288 // window gets the pending key event
8289 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8290}
Prabir Pradhan99987712020-11-10 18:43:05 -08008291
8292class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8293protected:
8294 std::shared_ptr<FakeApplicationHandle> mApp;
8295 sp<FakeWindowHandle> mWindow;
8296 sp<FakeWindowHandle> mSecondWindow;
8297
8298 void SetUp() override {
8299 InputDispatcherTest::SetUp();
8300 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008301 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008302 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008303 mSecondWindow =
8304 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008305 mSecondWindow->setFocusable(true);
8306
8307 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008308 mDispatcher->onWindowInfosChanged(
8309 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008310
8311 setFocusedWindow(mWindow);
8312 mWindow->consumeFocusEvent(true);
8313 }
8314
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008315 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008316 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008317 }
8318
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008319 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8320 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008321 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008322 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8323 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008324 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008325 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008326 }
8327};
8328
8329TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8330 // Ensure that capture cannot be obtained for unfocused windows.
8331 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8332 mFakePolicy->assertSetPointerCaptureNotCalled();
8333 mSecondWindow->assertNoEvents();
8334
8335 // Ensure that capture can be enabled from the focus window.
8336 requestAndVerifyPointerCapture(mWindow, true);
8337
8338 // Ensure that capture cannot be disabled from a window that does not have capture.
8339 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8340 mFakePolicy->assertSetPointerCaptureNotCalled();
8341
8342 // Ensure that capture can be disabled from the window with capture.
8343 requestAndVerifyPointerCapture(mWindow, false);
8344}
8345
8346TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008347 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008348
8349 setFocusedWindow(mSecondWindow);
8350
8351 // Ensure that the capture disabled event was sent first.
8352 mWindow->consumeCaptureEvent(false);
8353 mWindow->consumeFocusEvent(false);
8354 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008355 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008356
8357 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008358 notifyPointerCaptureChanged({});
8359 notifyPointerCaptureChanged(request);
8360 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008361 mWindow->assertNoEvents();
8362 mSecondWindow->assertNoEvents();
8363 mFakePolicy->assertSetPointerCaptureNotCalled();
8364}
8365
8366TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008367 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008368
8369 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008370 notifyPointerCaptureChanged({});
8371 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008372
8373 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008374 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008375 mWindow->consumeCaptureEvent(false);
8376 mWindow->assertNoEvents();
8377}
8378
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008379TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8380 requestAndVerifyPointerCapture(mWindow, true);
8381
8382 // The first window loses focus.
8383 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008384 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008385 mWindow->consumeCaptureEvent(false);
8386
8387 // Request Pointer Capture from the second window before the notification from InputReader
8388 // arrives.
8389 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008390 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008391
8392 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008393 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008394
8395 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008396 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008397
8398 mSecondWindow->consumeFocusEvent(true);
8399 mSecondWindow->consumeCaptureEvent(true);
8400}
8401
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008402TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8403 // App repeatedly enables and disables capture.
8404 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8405 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8406 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8407 mFakePolicy->assertSetPointerCaptureCalled(false);
8408 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8409 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8410
8411 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8412 // first request is now stale, this should do nothing.
8413 notifyPointerCaptureChanged(firstRequest);
8414 mWindow->assertNoEvents();
8415
8416 // InputReader notifies that the second request was enabled.
8417 notifyPointerCaptureChanged(secondRequest);
8418 mWindow->consumeCaptureEvent(true);
8419}
8420
Prabir Pradhan7092e262022-05-03 16:51:09 +00008421TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8422 requestAndVerifyPointerCapture(mWindow, true);
8423
8424 // App toggles pointer capture off and on.
8425 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8426 mFakePolicy->assertSetPointerCaptureCalled(false);
8427
8428 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8429 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8430
8431 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8432 // preceding "disable" request.
8433 notifyPointerCaptureChanged(enableRequest);
8434
8435 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8436 // any notifications.
8437 mWindow->assertNoEvents();
8438}
8439
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008440/**
8441 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8442 * mouse movements don't affect the previous mouse hovering state.
8443 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8444 * HOVER_MOVE events).
8445 */
8446TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8447 // Mouse hover on the window
8448 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8449 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8450 .build());
8451 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8452 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8453 .build());
8454
8455 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8456 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8457
8458 // Start pointer capture
8459 requestAndVerifyPointerCapture(mWindow, true);
8460
8461 // Send some relative mouse movements and receive them in the window.
8462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8463 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8464 .build());
8465 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8466 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8467
8468 // Stop pointer capture
8469 requestAndVerifyPointerCapture(mWindow, false);
8470
8471 // Continue hovering on the window
8472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8473 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8474 .build());
8475 mWindow->consumeMotionEvent(
8476 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8477
8478 mWindow->assertNoEvents();
8479}
8480
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008481class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8482protected:
8483 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008484
8485 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8486 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8487
8488 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8489 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8490
8491 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8492 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8493 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8494 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8495 MAXIMUM_OBSCURING_OPACITY);
8496
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008497 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8498 static constexpr gui::Uid APP_B_UID{10002};
8499 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008500
8501 sp<FakeWindowHandle> mTouchWindow;
8502
8503 virtual void SetUp() override {
8504 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008505 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008506 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8507 }
8508
8509 virtual void TearDown() override {
8510 InputDispatcherTest::TearDown();
8511 mTouchWindow.clear();
8512 }
8513
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008514 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008515 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008516 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008517 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008518 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008519 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008520 return window;
8521 }
8522
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008523 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008524 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8525 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008526 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008527 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008528 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008529 return window;
8530 }
8531
8532 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008533 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8534 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8535 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008536 }
8537};
8538
8539TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008540 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008541 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008542 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008543
8544 touch();
8545
8546 mTouchWindow->assertNoEvents();
8547}
8548
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008549TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008550 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8551 const sp<FakeWindowHandle>& w =
8552 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008553 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008554
8555 touch();
8556
8557 mTouchWindow->assertNoEvents();
8558}
8559
8560TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008561 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8562 const sp<FakeWindowHandle>& w =
8563 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008564 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008565
8566 touch();
8567
8568 w->assertNoEvents();
8569}
8570
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008571TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008572 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008573 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008574
8575 touch();
8576
8577 mTouchWindow->consumeAnyMotionDown();
8578}
8579
8580TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008581 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008582 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008583 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008584 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008585
8586 touch({PointF{100, 100}});
8587
8588 mTouchWindow->consumeAnyMotionDown();
8589}
8590
8591TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008592 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008593 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008594 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008595
8596 touch();
8597
8598 mTouchWindow->consumeAnyMotionDown();
8599}
8600
8601TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8602 const sp<FakeWindowHandle>& w =
8603 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008604 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008605
8606 touch();
8607
8608 mTouchWindow->consumeAnyMotionDown();
8609}
8610
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008611TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8612 const sp<FakeWindowHandle>& w =
8613 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008614 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008615
8616 touch();
8617
8618 w->assertNoEvents();
8619}
8620
8621/**
8622 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8623 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8624 * window, the occluding window will still receive ACTION_OUTSIDE event.
8625 */
8626TEST_F(InputDispatcherUntrustedTouchesTest,
8627 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8628 const sp<FakeWindowHandle>& w =
8629 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008630 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008631 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008632
8633 touch();
8634
8635 w->consumeMotionOutside();
8636}
8637
8638TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8639 const sp<FakeWindowHandle>& w =
8640 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008641 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008642 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008643
8644 touch();
8645
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008646 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008647}
8648
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008649TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008650 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008651 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8652 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008653 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008654
8655 touch();
8656
8657 mTouchWindow->consumeAnyMotionDown();
8658}
8659
8660TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8661 const sp<FakeWindowHandle>& w =
8662 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8663 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008664 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008665
8666 touch();
8667
8668 mTouchWindow->consumeAnyMotionDown();
8669}
8670
8671TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008672 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008673 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8674 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008675 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008676
8677 touch();
8678
8679 mTouchWindow->assertNoEvents();
8680}
8681
8682TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8683 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8684 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008685 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8686 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008687 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008688 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8689 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008690 mDispatcher->onWindowInfosChanged(
8691 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008692
8693 touch();
8694
8695 mTouchWindow->assertNoEvents();
8696}
8697
8698TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8699 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8700 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008701 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8702 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008703 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008704 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8705 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008706 mDispatcher->onWindowInfosChanged(
8707 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008708
8709 touch();
8710
8711 mTouchWindow->consumeAnyMotionDown();
8712}
8713
8714TEST_F(InputDispatcherUntrustedTouchesTest,
8715 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8716 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008717 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8718 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008719 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008720 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8721 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008722 mDispatcher->onWindowInfosChanged(
8723 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008724
8725 touch();
8726
8727 mTouchWindow->consumeAnyMotionDown();
8728}
8729
8730TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8731 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008732 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8733 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008734 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008735 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8736 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008737 mDispatcher->onWindowInfosChanged(
8738 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008739
8740 touch();
8741
8742 mTouchWindow->assertNoEvents();
8743}
8744
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008745TEST_F(InputDispatcherUntrustedTouchesTest,
8746 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8747 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008748 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8749 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008750 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008751 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8752 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008753 mDispatcher->onWindowInfosChanged(
8754 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008755
8756 touch();
8757
8758 mTouchWindow->assertNoEvents();
8759}
8760
8761TEST_F(InputDispatcherUntrustedTouchesTest,
8762 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8763 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008764 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8765 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008766 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008767 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8768 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008769 mDispatcher->onWindowInfosChanged(
8770 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008771
8772 touch();
8773
8774 mTouchWindow->consumeAnyMotionDown();
8775}
8776
8777TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8778 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008779 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8780 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008781 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008782
8783 touch();
8784
8785 mTouchWindow->consumeAnyMotionDown();
8786}
8787
8788TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8789 const sp<FakeWindowHandle>& w =
8790 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008791 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008792
8793 touch();
8794
8795 mTouchWindow->consumeAnyMotionDown();
8796}
8797
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008798TEST_F(InputDispatcherUntrustedTouchesTest,
8799 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8800 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8801 const sp<FakeWindowHandle>& w =
8802 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008803 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008804
8805 touch();
8806
8807 mTouchWindow->assertNoEvents();
8808}
8809
8810TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8811 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8812 const sp<FakeWindowHandle>& w =
8813 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008814 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008815
8816 touch();
8817
8818 mTouchWindow->consumeAnyMotionDown();
8819}
8820
8821TEST_F(InputDispatcherUntrustedTouchesTest,
8822 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8823 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8824 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008825 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8826 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008827 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008828
8829 touch();
8830
8831 mTouchWindow->consumeAnyMotionDown();
8832}
8833
8834TEST_F(InputDispatcherUntrustedTouchesTest,
8835 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8836 const sp<FakeWindowHandle>& w1 =
8837 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8838 OPACITY_BELOW_THRESHOLD);
8839 const sp<FakeWindowHandle>& w2 =
8840 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8841 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008842 mDispatcher->onWindowInfosChanged(
8843 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008844
8845 touch();
8846
8847 mTouchWindow->assertNoEvents();
8848}
8849
8850/**
8851 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8852 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8853 * (which alone would result in allowing touches) does not affect the blocking behavior.
8854 */
8855TEST_F(InputDispatcherUntrustedTouchesTest,
8856 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8857 const sp<FakeWindowHandle>& wB =
8858 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8859 OPACITY_BELOW_THRESHOLD);
8860 const sp<FakeWindowHandle>& wC =
8861 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8862 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008863 mDispatcher->onWindowInfosChanged(
8864 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008865
8866 touch();
8867
8868 mTouchWindow->assertNoEvents();
8869}
8870
8871/**
8872 * This test is testing that a window from a different UID but with same application token doesn't
8873 * block the touch. Apps can share the application token for close UI collaboration for example.
8874 */
8875TEST_F(InputDispatcherUntrustedTouchesTest,
8876 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8877 const sp<FakeWindowHandle>& w =
8878 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8879 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008880 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008881
8882 touch();
8883
8884 mTouchWindow->consumeAnyMotionDown();
8885}
8886
arthurhungb89ccb02020-12-30 16:19:01 +08008887class InputDispatcherDragTests : public InputDispatcherTest {
8888protected:
8889 std::shared_ptr<FakeApplicationHandle> mApp;
8890 sp<FakeWindowHandle> mWindow;
8891 sp<FakeWindowHandle> mSecondWindow;
8892 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008893 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008894 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8895 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008896
8897 void SetUp() override {
8898 InputDispatcherTest::SetUp();
8899 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008900 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008901 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008902
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008903 mSecondWindow =
8904 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008905 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008906
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008907 mSpyWindow =
8908 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008909 mSpyWindow->setSpy(true);
8910 mSpyWindow->setTrustedOverlay(true);
8911 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8912
arthurhungb89ccb02020-12-30 16:19:01 +08008913 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008914 mDispatcher->onWindowInfosChanged(
8915 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8916 {},
8917 0,
8918 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008919 }
8920
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008921 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8922 switch (fromSource) {
8923 case AINPUT_SOURCE_TOUCHSCREEN:
8924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008925 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008926 ADISPLAY_ID_DEFAULT, {50, 50}))
8927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8928 break;
8929 case AINPUT_SOURCE_STYLUS:
8930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008931 injectMotionEvent(*mDispatcher,
8932 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8933 AINPUT_SOURCE_STYLUS)
8934 .buttonState(
8935 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8936 .pointer(PointerBuilder(0, ToolType::STYLUS)
8937 .x(50)
8938 .y(50))
8939 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008940 break;
8941 case AINPUT_SOURCE_MOUSE:
8942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008943 injectMotionEvent(*mDispatcher,
8944 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8945 AINPUT_SOURCE_MOUSE)
8946 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8947 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8948 ToolType::MOUSE)
8949 .x(50)
8950 .y(50))
8951 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008952 break;
8953 default:
8954 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8955 }
arthurhungb89ccb02020-12-30 16:19:01 +08008956
8957 // Window should receive motion event.
8958 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008959 // Spy window should also receive motion event
8960 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008961 }
8962
8963 // Start performing drag, we will create a drag window and transfer touch to it.
8964 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8965 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008966 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008967 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008968 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008969 }
arthurhungb89ccb02020-12-30 16:19:01 +08008970
8971 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008972 mDragWindow =
8973 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008974 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008975 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8976 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8977 {},
8978 0,
8979 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008980
8981 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008982 bool transferred =
8983 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008984 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008985 if (transferred) {
8986 mWindow->consumeMotionCancel();
8987 mDragWindow->consumeMotionDown();
8988 }
8989 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008990 }
8991};
8992
8993TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008994 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008995
8996 // Move on window.
8997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008998 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008999 ADISPLAY_ID_DEFAULT, {50, 50}))
9000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9001 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9002 mWindow->consumeDragEvent(false, 50, 50);
9003 mSecondWindow->assertNoEvents();
9004
9005 // Move to another window.
9006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009007 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009008 ADISPLAY_ID_DEFAULT, {150, 50}))
9009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9010 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9011 mWindow->consumeDragEvent(true, 150, 50);
9012 mSecondWindow->consumeDragEvent(false, 50, 50);
9013
9014 // Move back to original window.
9015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009016 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009017 ADISPLAY_ID_DEFAULT, {50, 50}))
9018 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9019 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9020 mWindow->consumeDragEvent(false, 50, 50);
9021 mSecondWindow->consumeDragEvent(true, -50, 50);
9022
9023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009024 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9025 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9027 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9028 mWindow->assertNoEvents();
9029 mSecondWindow->assertNoEvents();
9030}
9031
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009032TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009033 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009034
9035 // No cancel event after drag start
9036 mSpyWindow->assertNoEvents();
9037
9038 const MotionEvent secondFingerDownEvent =
9039 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9040 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009041 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9042 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009043 .build();
9044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009045 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009046 InputEventInjectionSync::WAIT_FOR_RESULT))
9047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9048
9049 // Receives cancel for first pointer after next pointer down
9050 mSpyWindow->consumeMotionCancel();
9051 mSpyWindow->consumeMotionDown();
9052
9053 mSpyWindow->assertNoEvents();
9054}
9055
arthurhungf452d0b2021-01-06 00:19:52 +08009056TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009057 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009058
9059 // Move on window.
9060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009061 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009062 ADISPLAY_ID_DEFAULT, {50, 50}))
9063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9064 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9065 mWindow->consumeDragEvent(false, 50, 50);
9066 mSecondWindow->assertNoEvents();
9067
9068 // Move to another window.
9069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009070 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009071 ADISPLAY_ID_DEFAULT, {150, 50}))
9072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9073 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9074 mWindow->consumeDragEvent(true, 150, 50);
9075 mSecondWindow->consumeDragEvent(false, 50, 50);
9076
9077 // drop to another window.
9078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009079 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009080 {150, 50}))
9081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9082 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009083 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009084 mWindow->assertNoEvents();
9085 mSecondWindow->assertNoEvents();
9086}
9087
arthurhung6d4bed92021-03-17 11:59:33 +08009088TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009089 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009090
9091 // Move on window and keep button pressed.
9092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009093 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009094 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9095 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009096 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009097 .build()))
9098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9099 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9100 mWindow->consumeDragEvent(false, 50, 50);
9101 mSecondWindow->assertNoEvents();
9102
9103 // Move to another window and release button, expect to drop item.
9104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009105 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009106 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9107 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009108 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009109 .build()))
9110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9111 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9112 mWindow->assertNoEvents();
9113 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009114 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009115
9116 // nothing to the window.
9117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009118 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009119 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9120 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009121 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009122 .build()))
9123 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9124 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9125 mWindow->assertNoEvents();
9126 mSecondWindow->assertNoEvents();
9127}
9128
Arthur Hung54745652022-04-20 07:17:41 +00009129TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009130 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009131
9132 // Set second window invisible.
9133 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009134 mDispatcher->onWindowInfosChanged(
9135 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009136
9137 // Move on window.
9138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009139 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009140 ADISPLAY_ID_DEFAULT, {50, 50}))
9141 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9142 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9143 mWindow->consumeDragEvent(false, 50, 50);
9144 mSecondWindow->assertNoEvents();
9145
9146 // Move to another window.
9147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009148 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009149 ADISPLAY_ID_DEFAULT, {150, 50}))
9150 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9151 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9152 mWindow->consumeDragEvent(true, 150, 50);
9153 mSecondWindow->assertNoEvents();
9154
9155 // drop to another window.
9156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009157 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009158 {150, 50}))
9159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9160 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009161 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009162 mWindow->assertNoEvents();
9163 mSecondWindow->assertNoEvents();
9164}
9165
Arthur Hung54745652022-04-20 07:17:41 +00009166TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009167 // Ensure window could track pointerIds if it didn't support split touch.
9168 mWindow->setPreventSplitting(true);
9169
Arthur Hung54745652022-04-20 07:17:41 +00009170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009171 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009172 {50, 50}))
9173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9174 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9175
9176 const MotionEvent secondFingerDownEvent =
9177 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9178 .displayId(ADISPLAY_ID_DEFAULT)
9179 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009180 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9181 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009182 .build();
9183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009184 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009185 InputEventInjectionSync::WAIT_FOR_RESULT))
9186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009187 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009188
9189 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009190 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009191}
9192
9193TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9194 // First down on second window.
9195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009196 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009197 {150, 50}))
9198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9199
9200 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9201
9202 // Second down on first window.
9203 const MotionEvent secondFingerDownEvent =
9204 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9205 .displayId(ADISPLAY_ID_DEFAULT)
9206 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009207 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9208 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009209 .build();
9210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009211 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009212 InputEventInjectionSync::WAIT_FOR_RESULT))
9213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9214 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9215
9216 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009217 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009218
9219 // Move on window.
9220 const MotionEvent secondFingerMoveEvent =
9221 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9222 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009223 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9224 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009225 .build();
9226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009227 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009228 InputEventInjectionSync::WAIT_FOR_RESULT));
9229 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9230 mWindow->consumeDragEvent(false, 50, 50);
9231 mSecondWindow->consumeMotionMove();
9232
9233 // Release the drag pointer should perform drop.
9234 const MotionEvent secondFingerUpEvent =
9235 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9236 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009237 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9238 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009239 .build();
9240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009241 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009242 InputEventInjectionSync::WAIT_FOR_RESULT));
9243 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009244 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009245 mWindow->assertNoEvents();
9246 mSecondWindow->consumeMotionMove();
9247}
9248
Arthur Hung3915c1f2022-05-31 07:17:17 +00009249TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009250 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009251
9252 // Update window of second display.
9253 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009254 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009255 mDispatcher->onWindowInfosChanged(
9256 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9257 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9258 {},
9259 0,
9260 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009261
9262 // Let second display has a touch state.
9263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009264 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009265 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9266 AINPUT_SOURCE_TOUCHSCREEN)
9267 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009268 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009269 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009270 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009271 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009272 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009273 mDispatcher->onWindowInfosChanged(
9274 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9275 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9276 {},
9277 0,
9278 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009279
9280 // Move on window.
9281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009282 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009283 ADISPLAY_ID_DEFAULT, {50, 50}))
9284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9285 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9286 mWindow->consumeDragEvent(false, 50, 50);
9287 mSecondWindow->assertNoEvents();
9288
9289 // Move to another window.
9290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009291 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009292 ADISPLAY_ID_DEFAULT, {150, 50}))
9293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9294 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9295 mWindow->consumeDragEvent(true, 150, 50);
9296 mSecondWindow->consumeDragEvent(false, 50, 50);
9297
9298 // drop to another window.
9299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009300 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009301 {150, 50}))
9302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9303 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009304 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009305 mWindow->assertNoEvents();
9306 mSecondWindow->assertNoEvents();
9307}
9308
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009309TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9310 startDrag(true, AINPUT_SOURCE_MOUSE);
9311 // Move on window.
9312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009313 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009314 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9315 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009316 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009317 .x(50)
9318 .y(50))
9319 .build()))
9320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9321 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9322 mWindow->consumeDragEvent(false, 50, 50);
9323 mSecondWindow->assertNoEvents();
9324
9325 // Move to another window.
9326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009327 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009328 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9329 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009330 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009331 .x(150)
9332 .y(50))
9333 .build()))
9334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9335 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9336 mWindow->consumeDragEvent(true, 150, 50);
9337 mSecondWindow->consumeDragEvent(false, 50, 50);
9338
9339 // drop to another window.
9340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009341 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009342 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9343 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009344 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009345 .x(150)
9346 .y(50))
9347 .build()))
9348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9349 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009350 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009351 mWindow->assertNoEvents();
9352 mSecondWindow->assertNoEvents();
9353}
9354
Vishnu Nair062a8672021-09-03 16:07:44 -07009355class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9356
9357TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009359 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9360 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009361 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009362 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9363 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009364 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009365 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009366 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009367
9368 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009369 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009370 window->assertNoEvents();
9371
Prabir Pradhan678438e2023-04-13 19:32:51 +00009372 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9373 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009374 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9375 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009376 window->assertNoEvents();
9377
9378 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009379 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009381
Prabir Pradhan678438e2023-04-13 19:32:51 +00009382 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009383 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9384
Prabir Pradhan678438e2023-04-13 19:32:51 +00009385 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9386 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009387 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9388 window->assertNoEvents();
9389}
9390
9391TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9392 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9393 std::make_shared<FakeApplicationHandle>();
9394 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009395 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9396 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009397 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009398 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009399 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009401 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9402 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009403 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009404 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009405 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9406 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009407 mDispatcher->onWindowInfosChanged(
9408 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009409 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009410 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009411
9412 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009413 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009414 window->assertNoEvents();
9415
Prabir Pradhan678438e2023-04-13 19:32:51 +00009416 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9417 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009418 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9419 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009420 window->assertNoEvents();
9421
9422 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009423 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009424 mDispatcher->onWindowInfosChanged(
9425 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009426
Prabir Pradhan678438e2023-04-13 19:32:51 +00009427 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009428 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9429
Prabir Pradhan678438e2023-04-13 19:32:51 +00009430 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9431 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009432 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9433 window->assertNoEvents();
9434}
9435
9436TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9437 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9438 std::make_shared<FakeApplicationHandle>();
9439 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009440 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9441 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009442 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009443 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009444 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009446 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9447 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009448 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009449 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9451 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009452 mDispatcher->onWindowInfosChanged(
9453 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009454 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009455 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009456
9457 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009458 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009459 window->assertNoEvents();
9460
Prabir Pradhan678438e2023-04-13 19:32:51 +00009461 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9462 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009463 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9464 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009465 window->assertNoEvents();
9466
9467 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009468 mDispatcher->onWindowInfosChanged(
9469 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009470
Prabir Pradhan678438e2023-04-13 19:32:51 +00009471 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009472 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9473
Prabir Pradhan678438e2023-04-13 19:32:51 +00009474 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9475 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009476 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9477 window->assertNoEvents();
9478}
9479
Antonio Kantekf16f2832021-09-28 04:39:20 +00009480class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9481protected:
9482 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009483 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009484 sp<FakeWindowHandle> mWindow;
9485 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009486 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009487
9488 void SetUp() override {
9489 InputDispatcherTest::SetUp();
9490
9491 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009492 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009493 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009494 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009495 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009496 mSecondWindow =
9497 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009498 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009499 mThirdWindow =
9500 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9501 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9502 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009503
9504 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009505 mDispatcher->onWindowInfosChanged(
9506 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9507 {},
9508 0,
9509 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009510 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009511 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009512
Antonio Kantek15beb512022-06-13 22:35:41 +00009513 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009514 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009515 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009516 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9517 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009518 mThirdWindow->assertNoEvents();
9519 }
9520
9521 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9522 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009523 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009524 SECOND_DISPLAY_ID)) {
9525 mWindow->assertNoEvents();
9526 mSecondWindow->assertNoEvents();
9527 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009528 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009529 }
9530
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009531 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009532 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009533 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9534 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009535 mWindow->consumeTouchModeEvent(inTouchMode);
9536 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009537 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009538 }
9539};
9540
Antonio Kantek26defcf2022-02-08 01:12:27 +00009541TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009542 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009543 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9544 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009545 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009546}
9547
Antonio Kantek26defcf2022-02-08 01:12:27 +00009548TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9549 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009550 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009551 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009552 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009553 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009554 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009555 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009556 mWindow->assertNoEvents();
9557 mSecondWindow->assertNoEvents();
9558}
9559
9560TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9561 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009562 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009563 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009564 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009565 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009566 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009567}
9568
Antonio Kantekf16f2832021-09-28 04:39:20 +00009569TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009570 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009571 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9572 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009573 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009574 mWindow->assertNoEvents();
9575 mSecondWindow->assertNoEvents();
9576}
9577
Antonio Kantek15beb512022-06-13 22:35:41 +00009578TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9579 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9580 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9581 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009582 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009583 mWindow->assertNoEvents();
9584 mSecondWindow->assertNoEvents();
9585 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9586}
9587
Antonio Kantek48710e42022-03-24 14:19:30 -07009588TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9589 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9591 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009592 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9593 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9594
9595 // Then remove focus.
9596 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009597 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009598
9599 // Assert that caller can switch touch mode by owning one of the last interacted window.
9600 const WindowInfo& windowInfo = *mWindow->getInfo();
9601 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9602 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009603 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009604}
9605
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009606class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9607public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009608 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009609 std::shared_ptr<FakeApplicationHandle> application =
9610 std::make_shared<FakeApplicationHandle>();
9611 std::string name = "Fake Spy ";
9612 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009613 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9614 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009615 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009616 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009617 return spy;
9618 }
9619
9620 sp<FakeWindowHandle> createForeground() {
9621 std::shared_ptr<FakeApplicationHandle> application =
9622 std::make_shared<FakeApplicationHandle>();
9623 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009624 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9625 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009626 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009627 return window;
9628 }
9629
9630private:
9631 int mSpyCount{0};
9632};
9633
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009634using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009635/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009636 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9637 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009638TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009639 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009640 ScopedSilentDeath _silentDeath;
9641
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009642 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009643 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009644 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009645 ".* not a trusted overlay");
9646}
9647
9648/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009649 * Input injection into a display with a spy window but no foreground windows should succeed.
9650 */
9651TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009652 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009653 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009654
9655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009656 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9658 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9659}
9660
9661/**
9662 * Verify the order in which different input windows receive events. The touched foreground window
9663 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9664 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9665 * receive events before ones belows it.
9666 *
9667 * Here, we set up a scenario with four windows in the following Z order from the top:
9668 * spy1, spy2, window, spy3.
9669 * We then inject an event and verify that the foreground "window" receives it first, followed by
9670 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9671 * window.
9672 */
9673TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9674 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009675 auto spy1 = createSpy();
9676 auto spy2 = createSpy();
9677 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009678 mDispatcher->onWindowInfosChanged(
9679 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009680 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9681 const size_t numChannels = channels.size();
9682
Michael Wright8e9a8562022-02-09 13:44:29 +00009683 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009684 if (!epollFd.ok()) {
9685 FAIL() << "Failed to create epoll fd";
9686 }
9687
9688 for (size_t i = 0; i < numChannels; i++) {
9689 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9690 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9691 FAIL() << "Failed to add fd to epoll";
9692 }
9693 }
9694
9695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009696 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9698
9699 std::vector<size_t> eventOrder;
9700 std::vector<struct epoll_event> events(numChannels);
9701 for (;;) {
9702 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9703 (100ms).count());
9704 if (nFds < 0) {
9705 FAIL() << "Failed to call epoll_wait";
9706 }
9707 if (nFds == 0) {
9708 break; // epoll_wait timed out
9709 }
9710 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009711 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009712 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009713 channels[i]->consumeMotionDown();
9714 }
9715 }
9716
9717 // Verify the order in which the events were received.
9718 EXPECT_EQ(3u, eventOrder.size());
9719 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9720 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9721 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9722}
9723
9724/**
9725 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9726 */
9727TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9728 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009729 auto spy = createSpy();
9730 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009731 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009732
9733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009734 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9736 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9737 spy->assertNoEvents();
9738}
9739
9740/**
9741 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9742 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9743 * to the window.
9744 */
9745TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9746 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009747 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009748 spy->setTouchableRegion(Region{{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 touchable region.
9752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009753 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009754 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9755 window->consumeMotionDown();
9756 spy->assertNoEvents();
9757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009758 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9760 window->consumeMotionUp();
9761 spy->assertNoEvents();
9762
9763 // Inject an event inside the spy window's touchable region.
9764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009765 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009766 {5, 10}))
9767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9768 window->consumeMotionDown();
9769 spy->consumeMotionDown();
9770}
9771
9772/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009773 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009774 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009775 */
9776TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9777 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009778 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009779 auto spy = createSpy();
9780 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009781 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009782 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009783 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009784
9785 // Inject an event outside the spy window's frame and touchable region.
9786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009787 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009788 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009789 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9790 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009791 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009792}
9793
9794/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009795 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9796 * pointers that are down within its bounds.
9797 */
9798TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9799 auto windowLeft = createForeground();
9800 windowLeft->setFrame({0, 0, 100, 200});
9801 auto windowRight = createForeground();
9802 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009803 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009804 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009805 mDispatcher->onWindowInfosChanged(
9806 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009807
9808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009809 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009810 {50, 50}))
9811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9812 windowLeft->consumeMotionDown();
9813 spy->consumeMotionDown();
9814
9815 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009816 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009817 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009818 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9819 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009820 .build();
9821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009822 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009823 InputEventInjectionSync::WAIT_FOR_RESULT))
9824 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9825 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009826 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009827}
9828
9829/**
9830 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9831 * the spy should receive the second pointer with ACTION_DOWN.
9832 */
9833TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9834 auto window = createForeground();
9835 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009836 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009837 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009838 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009839
9840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009841 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009842 {50, 50}))
9843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9844 window->consumeMotionDown();
9845 spyRight->assertNoEvents();
9846
9847 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009848 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009849 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009850 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9851 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009852 .build();
9853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009854 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009855 InputEventInjectionSync::WAIT_FOR_RESULT))
9856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009857 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009858 spyRight->consumeMotionDown();
9859}
9860
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009861/**
9862 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9863 * windows should be allowed to control split touch.
9864 */
9865TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009866 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009867 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009868 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009869 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009870
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009871 auto window = createForeground();
9872 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009873
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009874 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009875
9876 // First finger down, no window touched.
9877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009878 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009879 {100, 200}))
9880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9881 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9882 window->assertNoEvents();
9883
9884 // Second finger down on window, the window should receive touch down.
9885 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009886 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009887 .displayId(ADISPLAY_ID_DEFAULT)
9888 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009889 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9890 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009891 .build();
9892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009893 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009894 InputEventInjectionSync::WAIT_FOR_RESULT))
9895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9896
9897 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009898 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009899}
9900
9901/**
9902 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9903 * do not receive key events.
9904 */
9905TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009906 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009907 spy->setFocusable(false);
9908
9909 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009910 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009911 setFocusedWindow(window);
9912 window->consumeFocusEvent(true);
9913
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009915 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9916 window->consumeKeyDown(ADISPLAY_ID_NONE);
9917
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009919 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9920 window->consumeKeyUp(ADISPLAY_ID_NONE);
9921
9922 spy->assertNoEvents();
9923}
9924
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009925using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9926
9927/**
9928 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9929 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9930 */
9931TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9932 auto window = createForeground();
9933 auto spy1 = createSpy();
9934 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009935 mDispatcher->onWindowInfosChanged(
9936 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009937
9938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009939 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9941 window->consumeMotionDown();
9942 spy1->consumeMotionDown();
9943 spy2->consumeMotionDown();
9944
9945 // Pilfer pointers from the second spy window.
9946 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9947 spy2->assertNoEvents();
9948 spy1->consumeMotionCancel();
9949 window->consumeMotionCancel();
9950
9951 // The rest of the gesture should only be sent to the second spy window.
9952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009953 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009954 ADISPLAY_ID_DEFAULT))
9955 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9956 spy2->consumeMotionMove();
9957 spy1->assertNoEvents();
9958 window->assertNoEvents();
9959}
9960
9961/**
9962 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9963 * in the middle of the gesture.
9964 */
9965TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9966 auto window = createForeground();
9967 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009968 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009969
9970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009971 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9973 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9974 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9975
9976 window->releaseChannel();
9977
9978 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9979
9980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009981 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009982 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9983 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9984}
9985
9986/**
9987 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9988 * the spy, but not to any other windows.
9989 */
9990TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9991 auto spy = createSpy();
9992 auto window = createForeground();
9993
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009994 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009995
9996 // First finger down on the window and the spy.
9997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009998 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009999 {100, 200}))
10000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10001 spy->consumeMotionDown();
10002 window->consumeMotionDown();
10003
10004 // Spy window pilfers the pointers.
10005 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10006 window->consumeMotionCancel();
10007
10008 // Second finger down on the window and spy, but the window should not receive the pointer down.
10009 const MotionEvent secondFingerDownEvent =
10010 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10011 .displayId(ADISPLAY_ID_DEFAULT)
10012 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010013 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10014 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010015 .build();
10016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010017 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010018 InputEventInjectionSync::WAIT_FOR_RESULT))
10019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10020
Harry Cutts33476232023-01-30 19:57:29 +000010021 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010022
10023 // Third finger goes down outside all windows, so injection should fail.
10024 const MotionEvent thirdFingerDownEvent =
10025 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10026 .displayId(ADISPLAY_ID_DEFAULT)
10027 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010028 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10029 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10030 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010031 .build();
10032 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010033 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010034 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010035 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010036
10037 spy->assertNoEvents();
10038 window->assertNoEvents();
10039}
10040
10041/**
10042 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10043 */
10044TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10045 auto spy = createSpy();
10046 spy->setFrame(Rect(0, 0, 100, 100));
10047 auto window = createForeground();
10048 window->setFrame(Rect(0, 0, 200, 200));
10049
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010050 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010051
10052 // First finger down on the window only
10053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010054 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010055 {150, 150}))
10056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10057 window->consumeMotionDown();
10058
10059 // Second finger down on the spy and window
10060 const MotionEvent secondFingerDownEvent =
10061 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10062 .displayId(ADISPLAY_ID_DEFAULT)
10063 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010064 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10065 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010066 .build();
10067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010068 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010069 InputEventInjectionSync::WAIT_FOR_RESULT))
10070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10071 spy->consumeMotionDown();
10072 window->consumeMotionPointerDown(1);
10073
10074 // Third finger down on the spy and window
10075 const MotionEvent thirdFingerDownEvent =
10076 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10077 .displayId(ADISPLAY_ID_DEFAULT)
10078 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010079 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10080 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10081 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010082 .build();
10083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010084 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010085 InputEventInjectionSync::WAIT_FOR_RESULT))
10086 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10087 spy->consumeMotionPointerDown(1);
10088 window->consumeMotionPointerDown(2);
10089
10090 // Spy window pilfers the pointers.
10091 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010092 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10093 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010094
10095 spy->assertNoEvents();
10096 window->assertNoEvents();
10097}
10098
10099/**
10100 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10101 * other windows should be canceled. If this results in the cancellation of all pointers for some
10102 * window, then that window should receive ACTION_CANCEL.
10103 */
10104TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10105 auto spy = createSpy();
10106 spy->setFrame(Rect(0, 0, 100, 100));
10107 auto window = createForeground();
10108 window->setFrame(Rect(0, 0, 200, 200));
10109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010110 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010111
10112 // First finger down on both spy and window
10113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010114 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010115 {10, 10}))
10116 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10117 window->consumeMotionDown();
10118 spy->consumeMotionDown();
10119
10120 // Second finger down on the spy and window
10121 const MotionEvent secondFingerDownEvent =
10122 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10123 .displayId(ADISPLAY_ID_DEFAULT)
10124 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010125 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10126 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010127 .build();
10128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010129 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010130 InputEventInjectionSync::WAIT_FOR_RESULT))
10131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10132 spy->consumeMotionPointerDown(1);
10133 window->consumeMotionPointerDown(1);
10134
10135 // Spy window pilfers the pointers.
10136 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10137 window->consumeMotionCancel();
10138
10139 spy->assertNoEvents();
10140 window->assertNoEvents();
10141}
10142
10143/**
10144 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10145 * be sent to other windows
10146 */
10147TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10148 auto spy = createSpy();
10149 spy->setFrame(Rect(0, 0, 100, 100));
10150 auto window = createForeground();
10151 window->setFrame(Rect(0, 0, 200, 200));
10152
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010153 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010154
10155 // First finger down on both window and spy
10156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010157 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010158 {10, 10}))
10159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10160 window->consumeMotionDown();
10161 spy->consumeMotionDown();
10162
10163 // Spy window pilfers the pointers.
10164 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10165 window->consumeMotionCancel();
10166
10167 // Second finger down on the window only
10168 const MotionEvent secondFingerDownEvent =
10169 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10170 .displayId(ADISPLAY_ID_DEFAULT)
10171 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010172 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10173 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010174 .build();
10175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010176 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010177 InputEventInjectionSync::WAIT_FOR_RESULT))
10178 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10179 window->consumeMotionDown();
10180 window->assertNoEvents();
10181
10182 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10183 spy->consumeMotionMove();
10184 spy->assertNoEvents();
10185}
10186
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010187/**
10188 * A window on the left and a window on the right. Also, a spy window that's above all of the
10189 * windows, and spanning both left and right windows.
10190 * Send simultaneous motion streams from two different devices, one to the left window, and another
10191 * to the right window.
10192 * Pilfer from spy window.
10193 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10194 */
10195TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10196 sp<FakeWindowHandle> spy = createSpy();
10197 spy->setFrame(Rect(0, 0, 200, 200));
10198 sp<FakeWindowHandle> leftWindow = createForeground();
10199 leftWindow->setFrame(Rect(0, 0, 100, 100));
10200
10201 sp<FakeWindowHandle> rightWindow = createForeground();
10202 rightWindow->setFrame(Rect(100, 0, 200, 100));
10203
10204 constexpr int32_t stylusDeviceId = 1;
10205 constexpr int32_t touchDeviceId = 2;
10206
10207 mDispatcher->onWindowInfosChanged(
10208 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10209
10210 // Stylus down on left window and spy
10211 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10212 .deviceId(stylusDeviceId)
10213 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10214 .build());
10215 leftWindow->consumeMotionEvent(
10216 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10217 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10218
10219 // Finger down on right window and spy - but spy already has stylus
10220 mDispatcher->notifyMotion(
10221 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10222 .deviceId(touchDeviceId)
10223 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10224 .build());
10225 rightWindow->consumeMotionEvent(
10226 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10227 leftWindow->consumeMotionEvent(
10228 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10229 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10230 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10231
10232 // Act: pilfer from spy. Spy is currently receiving touch events.
10233 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10234 rightWindow->consumeMotionEvent(
10235 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10236
10237 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10238 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10239 .deviceId(stylusDeviceId)
10240 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10241 .build());
10242 mDispatcher->notifyMotion(
10243 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10244 .deviceId(touchDeviceId)
10245 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10246 .build());
10247 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10248
10249 spy->assertNoEvents();
10250 leftWindow->assertNoEvents();
10251 rightWindow->assertNoEvents();
10252}
10253
Prabir Pradhand65552b2021-10-07 11:23:50 -070010254class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10255public:
10256 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10257 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10258 std::make_shared<FakeApplicationHandle>();
10259 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010260 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10261 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010262 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010263 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010264 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010265 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010266 overlay->setTrustedOverlay(true);
10267
10268 std::shared_ptr<FakeApplicationHandle> application =
10269 std::make_shared<FakeApplicationHandle>();
10270 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010271 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10272 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010273 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010274 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010275
10276 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010277 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010278 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010279 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010280 return {std::move(overlay), std::move(window)};
10281 }
10282
10283 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010284 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010285 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010286 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010287 }
10288
10289 void sendStylusEvent(int32_t action) {
10290 NotifyMotionArgs motionArgs =
10291 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10292 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010293 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010294 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010295 }
10296};
10297
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010298using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10299
10300TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010301 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010302 ScopedSilentDeath _silentDeath;
10303
Prabir Pradhand65552b2021-10-07 11:23:50 -070010304 auto [overlay, window] = setupStylusOverlayScenario();
10305 overlay->setTrustedOverlay(false);
10306 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010307 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10308 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010309 ".* not a trusted overlay");
10310}
10311
10312TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10313 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010314 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010315
10316 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10317 overlay->consumeMotionDown();
10318 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10319 overlay->consumeMotionUp();
10320
10321 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10322 window->consumeMotionDown();
10323 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10324 window->consumeMotionUp();
10325
10326 overlay->assertNoEvents();
10327 window->assertNoEvents();
10328}
10329
10330TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10331 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010332 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010333 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010334
10335 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10336 overlay->consumeMotionDown();
10337 window->consumeMotionDown();
10338 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10339 overlay->consumeMotionUp();
10340 window->consumeMotionUp();
10341
10342 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10343 window->consumeMotionDown();
10344 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10345 window->consumeMotionUp();
10346
10347 overlay->assertNoEvents();
10348 window->assertNoEvents();
10349}
10350
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010351/**
10352 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10353 * The scenario is as follows:
10354 * - The stylus interceptor overlay is configured as a spy window.
10355 * - The stylus interceptor spy receives the start of a new stylus gesture.
10356 * - It pilfers pointers and then configures itself to no longer be a spy.
10357 * - The stylus interceptor continues to receive the rest of the gesture.
10358 */
10359TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10360 auto [overlay, window] = setupStylusOverlayScenario();
10361 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010362 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010363
10364 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10365 overlay->consumeMotionDown();
10366 window->consumeMotionDown();
10367
10368 // The interceptor pilfers the pointers.
10369 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10370 window->consumeMotionCancel();
10371
10372 // The interceptor configures itself so that it is no longer a spy.
10373 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010374 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010375
10376 // It continues to receive the rest of the stylus gesture.
10377 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10378 overlay->consumeMotionMove();
10379 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10380 overlay->consumeMotionUp();
10381
10382 window->assertNoEvents();
10383}
10384
Prabir Pradhan5735a322022-04-11 17:23:34 +000010385struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010386 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010387 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010388 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10389 std::unique_ptr<InputDispatcher>& mDispatcher;
10390
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010391 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010392 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10393
10394 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010395 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010396 ADISPLAY_ID_DEFAULT, {100, 200},
10397 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10398 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10399 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10400 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10401 }
10402
10403 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010404 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010405 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010406 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010407 mPolicyFlags);
10408 }
10409
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010410 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010411 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10412 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010413 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10414 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010415 window->setOwnerInfo(mPid, mUid);
10416 return window;
10417 }
10418};
10419
10420using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10421
10422TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
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");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010425 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010426
10427 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10428 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10429 window->consumeMotionDown();
10430
10431 setFocusedWindow(window);
10432 window->consumeFocusEvent(true);
10433
10434 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10435 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10436 window->consumeKeyDown(ADISPLAY_ID_NONE);
10437}
10438
10439TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010440 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010441 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010442 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010443
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010444 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010445 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10446 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10447
10448 setFocusedWindow(window);
10449 window->consumeFocusEvent(true);
10450
10451 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10452 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10453 window->assertNoEvents();
10454}
10455
10456TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010457 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010458 auto window = owner.createWindow("Owned window");
10459 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010460 spy->setSpy(true);
10461 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010462 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010463
10464 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10465 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10466 spy->consumeMotionDown();
10467 window->consumeMotionDown();
10468}
10469
10470TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010471 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010472 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010473
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010474 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010475 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010476 randosSpy->setSpy(true);
10477 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010478 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010479
10480 // The event is targeted at owner's window, so injection should succeed, but the spy should
10481 // not receive the event.
10482 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10483 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10484 randosSpy->assertNoEvents();
10485 window->consumeMotionDown();
10486}
10487
10488TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010489 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010490 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010491
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010492 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010493 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010494 randosSpy->setSpy(true);
10495 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010496 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010497
10498 // A user that has injection permission can inject into any window.
10499 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010500 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010501 ADISPLAY_ID_DEFAULT));
10502 randosSpy->consumeMotionDown();
10503 window->consumeMotionDown();
10504
10505 setFocusedWindow(randosSpy);
10506 randosSpy->consumeFocusEvent(true);
10507
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010508 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010509 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10510 window->assertNoEvents();
10511}
10512
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010513TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010514 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010515 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010516
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010517 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010518 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010519 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10520 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010521 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010522
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010523 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010524 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10525 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10526 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010527 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010528}
10529
Garfield Tane84e6f92019-08-29 17:28:41 -070010530} // namespace android::inputdispatcher