blob: c3c883774e691ddd9bf6055c493f70480fbc05ff [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:
Prabir Pradhanfb549072023-10-05 19:17:36 +00001456 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId) {
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001457 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhanfb549072023-10-05 19:17:36 +00001458 dispatcher.createInputMonitor(displayId, name, MONITOR_PID);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001459 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
1460 }
1461
1462 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
1463
1464 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1465 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1466 expectedFlags);
1467 }
1468
1469 std::optional<int32_t> receiveEvent() {
1470 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1471 }
1472
1473 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
1474
1475 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1476 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1477 expectedDisplayId, expectedFlags);
1478 }
1479
1480 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1481 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1482 expectedDisplayId, expectedFlags);
1483 }
1484
1485 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1486 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1487 expectedDisplayId, expectedFlags);
1488 }
1489
1490 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1491 mInputReceiver->consumeMotionEvent(
1492 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1493 WithDisplayId(expectedDisplayId),
1494 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1495 }
1496
1497 void consumeMotionPointerDown(int32_t pointerIdx) {
1498 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1499 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1500 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1501 /*expectedFlags=*/0);
1502 }
1503
1504 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1505 mInputReceiver->consumeMotionEvent(matcher);
1506 }
1507
1508 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
1509
1510 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
1511
1512private:
1513 std::unique_ptr<FakeInputReceiver> mInputReceiver;
1514};
1515
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001516static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001517 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001518 int32_t displayId = ADISPLAY_ID_NONE,
1519 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001520 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001521 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001522 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001523 KeyEvent event;
1524 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1525
1526 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001527 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001528 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1529 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001530
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001531 if (!allowKeyRepeat) {
1532 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1533 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001534 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001535 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001536}
1537
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001538static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1539 InputEventInjectionResult result =
1540 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1541 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1542 if (result != InputEventInjectionResult::TIMED_OUT) {
1543 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1544 }
1545}
1546
1547static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001548 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001549 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001550}
1551
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001552// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1553// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1554// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001555static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1556 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001557 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001558 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001559 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001560}
1561
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001562static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001563 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001564 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001565}
1566
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001567static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001568 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001569 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001570 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001571 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001572 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1573 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001574}
1575
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001576static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001577 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1578 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001579 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001580 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1581 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001582 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001583 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001584 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001585 MotionEventBuilder motionBuilder =
1586 MotionEventBuilder(action, source)
1587 .displayId(displayId)
1588 .eventTime(eventTime)
1589 .rawXCursorPosition(cursorPosition.x)
1590 .rawYCursorPosition(cursorPosition.y)
1591 .pointer(
1592 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1593 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1594 motionBuilder.downTime(eventTime);
1595 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001596
1597 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001598 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1599 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001600}
1601
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001602static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1603 int32_t displayId,
1604 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001605 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001606}
1607
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001608static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1609 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001610 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001611 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001612}
1613
Jackal Guof9696682018-10-05 12:23:23 +08001614static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1615 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1616 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001617 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001618 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1619 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001620
1621 return args;
1622}
1623
Josep del Riob3981622023-04-18 15:49:45 +00001624static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1625 int32_t displayId = ADISPLAY_ID_NONE) {
1626 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1627 // Define a valid key event.
1628 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001629 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001630 currentTime);
1631
1632 return args;
1633}
1634
1635static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1636 int32_t displayId = ADISPLAY_ID_NONE) {
1637 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1638 // Define a valid key event.
1639 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001640 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001641 AMETA_NONE, currentTime);
1642
1643 return args;
1644}
1645
Prabir Pradhan678438e2023-04-13 19:32:51 +00001646[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1647 int32_t displayId,
1648 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001649 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001650 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1651 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1652 }
1653
chaviwd1c23182019-12-20 18:44:56 -08001654 PointerProperties pointerProperties[pointerCount];
1655 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001656
chaviwd1c23182019-12-20 18:44:56 -08001657 for (size_t i = 0; i < pointerCount; i++) {
1658 pointerProperties[i].clear();
1659 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001660 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001661
chaviwd1c23182019-12-20 18:44:56 -08001662 pointerCoords[i].clear();
1663 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1664 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1665 }
Jackal Guof9696682018-10-05 12:23:23 +08001666
1667 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1668 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001669 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001670 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1671 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001672 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001673 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001674 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001675 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001676
1677 return args;
1678}
1679
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001680static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1681 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1682}
1683
chaviwd1c23182019-12-20 18:44:56 -08001684static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1685 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1686}
1687
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001688static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1689 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001690 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001691}
1692
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001693} // namespace
1694
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001695/**
1696 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1697 * broken channel.
1698 */
1699TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1701 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001702 sp<FakeWindowHandle>::make(application, mDispatcher,
1703 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001706
1707 // Window closes its channel, but the window remains.
1708 window->destroyReceiver();
1709 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1710}
1711
Arthur Hungb92218b2018-08-14 12:00:21 +08001712TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1715 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001719 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001721
1722 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001723 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001724}
1725
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001726TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001728 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1729 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001730
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001731 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001732 // Inject a MotionEvent to an unknown display.
1733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001734 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1736
1737 // Window should receive motion event.
1738 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1739}
1740
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001741/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001742 * Calling onWindowInfosChanged once should not cause any issues.
1743 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001744 * called twice.
1745 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001746TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001748 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1749 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001750 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001751
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001754 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001755 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001757
1758 // Window should receive motion event.
1759 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1760}
1761
1762/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001763 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001764 */
1765TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001767 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1768 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001769 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001770
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001771 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1772 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001774 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001775 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001776 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001777
1778 // Window should receive motion event.
1779 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1780}
1781
Arthur Hungb92218b2018-08-14 12:00:21 +08001782// The foreground window should receive the first touch down event.
1783TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001785 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001786 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001787 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001788 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001789
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001790 mDispatcher->onWindowInfosChanged(
1791 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001793 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001795
1796 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001797 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001798 windowSecond->assertNoEvents();
1799}
1800
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001801/**
1802 * Two windows: A top window, and a wallpaper behind the window.
1803 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1804 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001805 * 1. foregroundWindow <-- dup touch to wallpaper
1806 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001807 */
1808TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1810 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001811 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001812 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001813 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001814 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001815 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001816
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001817 mDispatcher->onWindowInfosChanged(
1818 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001820 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001821 {100, 200}))
1822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1823
1824 // Both foreground window and its wallpaper should receive the touch down
1825 foregroundWindow->consumeMotionDown();
1826 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1827
1828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001829 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001830 ADISPLAY_ID_DEFAULT, {110, 200}))
1831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1832
1833 foregroundWindow->consumeMotionMove();
1834 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1835
1836 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001837 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001838 foregroundWindow->consumeMotionCancel();
1839 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1840 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1841}
1842
1843/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001844 * Two fingers down on the window, and lift off the first finger.
1845 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1846 * contains a single pointer.
1847 */
1848TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1850 sp<FakeWindowHandle> window =
1851 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1852
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001853 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001854 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1856 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1857 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001858 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001859 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1860 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1861 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1862 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001863 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001864 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1865 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1866 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1867 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001868 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1869 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1870 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1871
1872 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001873 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001874 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1875 window->consumeMotionEvent(
1876 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1877}
1878
1879/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001880 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1881 * with the following differences:
1882 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1883 * clean up the connection.
1884 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1885 * Ensure that there's no crash in the dispatcher.
1886 */
1887TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1889 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001890 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001891 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001892 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001893 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001894 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001895
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001896 mDispatcher->onWindowInfosChanged(
1897 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001899 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001900 {100, 200}))
1901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1902
1903 // Both foreground window and its wallpaper should receive the touch down
1904 foregroundWindow->consumeMotionDown();
1905 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1906
1907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001908 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001909 ADISPLAY_ID_DEFAULT, {110, 200}))
1910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1911
1912 foregroundWindow->consumeMotionMove();
1913 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1914
1915 // Wallpaper closes its channel, but the window remains.
1916 wallpaperWindow->destroyReceiver();
1917 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1918
1919 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1920 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001921 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001922 foregroundWindow->consumeMotionCancel();
1923}
1924
Arthur Hungc539dbb2022-12-08 07:45:36 +00001925class ShouldSplitTouchFixture : public InputDispatcherTest,
1926 public ::testing::WithParamInterface<bool> {};
1927INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1928 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001929/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001930 * A single window that receives touch (on top), and a wallpaper window underneath it.
1931 * The top window gets a multitouch gesture.
1932 * Ensure that wallpaper gets the same gesture.
1933 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001934TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001936 sp<FakeWindowHandle> foregroundWindow =
1937 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1938 foregroundWindow->setDupTouchToWallpaper(true);
1939 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001940
1941 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001942 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001943 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001944
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001945 mDispatcher->onWindowInfosChanged(
1946 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001947
1948 // Touch down on top window
1949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001950 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001951 {100, 100}))
1952 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1953
1954 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001955 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1957
1958 // Second finger down on the top window
1959 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001960 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001961 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001962 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1963 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001964 .build();
1965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001966 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001967 InputEventInjectionSync::WAIT_FOR_RESULT))
1968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1969
Harry Cutts33476232023-01-30 19:57:29 +00001970 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1971 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001973
1974 const MotionEvent secondFingerUpEvent =
1975 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1976 .displayId(ADISPLAY_ID_DEFAULT)
1977 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001978 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1979 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001980 .build();
1981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001982 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001983 InputEventInjectionSync::WAIT_FOR_RESULT))
1984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1985 foregroundWindow->consumeMotionPointerUp(0);
1986 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1987
1988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001989 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001990 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1991 AINPUT_SOURCE_TOUCHSCREEN)
1992 .displayId(ADISPLAY_ID_DEFAULT)
1993 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001994 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001995 .x(100)
1996 .y(100))
1997 .build(),
1998 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2000 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2001 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002002}
2003
2004/**
2005 * Two windows: a window on the left and window on the right.
2006 * A third window, wallpaper, is behind both windows, and spans both top windows.
2007 * The first touch down goes to the left window. A second pointer touches down on the right window.
2008 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2009 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2010 * ACTION_POINTER_DOWN(1).
2011 */
2012TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2014 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002015 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002016 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002017 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002018
2019 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002020 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002022 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023
2024 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002025 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002027 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002028
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002029 mDispatcher->onWindowInfosChanged(
2030 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2031 {},
2032 0,
2033 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002034
2035 // Touch down on left window
2036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002037 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 {100, 100}))
2039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2040
2041 // Both foreground window and its wallpaper should receive the touch down
2042 leftWindow->consumeMotionDown();
2043 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2044
2045 // Second finger down on the right window
2046 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002047 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002048 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002049 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2050 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002051 .build();
2052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002053 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002054 InputEventInjectionSync::WAIT_FOR_RESULT))
2055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2056
2057 leftWindow->consumeMotionMove();
2058 // Since the touch is split, right window gets ACTION_DOWN
2059 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002060 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002061 expectedWallpaperFlags);
2062
2063 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002064 mDispatcher->onWindowInfosChanged(
2065 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002066 leftWindow->consumeMotionCancel();
2067 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2068 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2069
2070 // The pointer that's still down on the right window moves, and goes to the right window only.
2071 // As far as the dispatcher's concerned though, both pointers are still present.
2072 const MotionEvent secondFingerMoveEvent =
2073 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2074 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002075 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2076 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002077 .build();
2078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002079 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002080 InputEventInjectionSync::WAIT_FOR_RESULT));
2081 rightWindow->consumeMotionMove();
2082
2083 leftWindow->assertNoEvents();
2084 rightWindow->assertNoEvents();
2085 wallpaperWindow->assertNoEvents();
2086}
2087
Arthur Hungc539dbb2022-12-08 07:45:36 +00002088/**
2089 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2090 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2091 * The right window should receive ACTION_DOWN.
2092 */
2093TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002095 sp<FakeWindowHandle> leftWindow =
2096 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2097 leftWindow->setFrame(Rect(0, 0, 200, 200));
2098 leftWindow->setDupTouchToWallpaper(true);
2099 leftWindow->setSlippery(true);
2100
2101 sp<FakeWindowHandle> rightWindow =
2102 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2103 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002104
2105 sp<FakeWindowHandle> wallpaperWindow =
2106 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2107 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002108
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002109 mDispatcher->onWindowInfosChanged(
2110 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2111 {},
2112 0,
2113 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002114
Arthur Hungc539dbb2022-12-08 07:45:36 +00002115 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002117 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002118 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002119 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002120
2121 // Both foreground window and its wallpaper should receive the touch down
2122 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002123 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2124
Arthur Hungc539dbb2022-12-08 07:45:36 +00002125 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002127 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002128 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2130
Arthur Hungc539dbb2022-12-08 07:45:36 +00002131 leftWindow->consumeMotionCancel();
2132 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2133 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002134}
2135
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002136/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002137 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2138 * interactive, it might stop sending this flag.
2139 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2140 * to have a consistent input stream.
2141 *
2142 * Test procedure:
2143 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2144 * DOWN (new gesture).
2145 *
2146 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2147 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2148 *
2149 * We technically just need a single window here, but we are using two windows (spy on top and a
2150 * regular window below) to emulate the actual situation where it happens on the device.
2151 */
2152TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2153 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2154 sp<FakeWindowHandle> spyWindow =
2155 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2156 spyWindow->setFrame(Rect(0, 0, 200, 200));
2157 spyWindow->setTrustedOverlay(true);
2158 spyWindow->setSpy(true);
2159
2160 sp<FakeWindowHandle> window =
2161 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2162 window->setFrame(Rect(0, 0, 200, 200));
2163
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002164 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002165 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002166
2167 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002168 mDispatcher->notifyMotion(
2169 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2170 .deviceId(touchDeviceId)
2171 .policyFlags(DEFAULT_POLICY_FLAGS)
2172 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2173 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002174
Prabir Pradhan678438e2023-04-13 19:32:51 +00002175 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2176 .deviceId(touchDeviceId)
2177 .policyFlags(DEFAULT_POLICY_FLAGS)
2178 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2179 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2180 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002181 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2182 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2183 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2184 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2185
2186 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002187 mDispatcher->notifyMotion(
2188 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2189 .deviceId(touchDeviceId)
2190 .policyFlags(0)
2191 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2192 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2193 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002194 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2195 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2196
2197 // We don't need to reset the device to reproduce the issue, but the reset event typically
2198 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002199 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002200
2201 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002202 mDispatcher->notifyMotion(
2203 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2204 .deviceId(touchDeviceId)
2205 .policyFlags(DEFAULT_POLICY_FLAGS)
2206 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2207 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002208 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2209 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2210
2211 // No more events
2212 spyWindow->assertNoEvents();
2213 window->assertNoEvents();
2214}
2215
2216/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002217 * Two windows: a window on the left and a window on the right.
2218 * Mouse is hovered from the right window into the left window.
2219 * Next, we tap on the left window, where the cursor was last seen.
2220 * The second tap is done onto the right window.
2221 * The mouse and tap are from two different devices.
2222 * We technically don't need to set the downtime / eventtime for these events, but setting these
2223 * explicitly helps during debugging.
2224 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2225 * In the buggy implementation, a tap on the right window would cause a crash.
2226 */
2227TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2228 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2229 sp<FakeWindowHandle> leftWindow =
2230 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2231 leftWindow->setFrame(Rect(0, 0, 200, 200));
2232
2233 sp<FakeWindowHandle> rightWindow =
2234 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2235 rightWindow->setFrame(Rect(200, 0, 400, 200));
2236
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002237 mDispatcher->onWindowInfosChanged(
2238 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002239 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2240 // stale.
2241 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2242 const int32_t mouseDeviceId = 6;
2243 const int32_t touchDeviceId = 4;
2244 // Move the cursor from right
2245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002246 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002247 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2248 AINPUT_SOURCE_MOUSE)
2249 .deviceId(mouseDeviceId)
2250 .downTime(baseTime + 10)
2251 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002252 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002253 .build()));
2254 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2255
2256 // .. to the left window
2257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002258 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002259 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2260 AINPUT_SOURCE_MOUSE)
2261 .deviceId(mouseDeviceId)
2262 .downTime(baseTime + 10)
2263 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002264 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002265 .build()));
2266 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2267 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2268 // Now tap the left window
2269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2272 AINPUT_SOURCE_TOUCHSCREEN)
2273 .deviceId(touchDeviceId)
2274 .downTime(baseTime + 40)
2275 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 .build()));
2278 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2279 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2280
2281 // release tap
2282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002283 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002284 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2285 AINPUT_SOURCE_TOUCHSCREEN)
2286 .deviceId(touchDeviceId)
2287 .downTime(baseTime + 40)
2288 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002289 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002290 .build()));
2291 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2292
2293 // Tap the window on the right
2294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002295 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002296 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2297 AINPUT_SOURCE_TOUCHSCREEN)
2298 .deviceId(touchDeviceId)
2299 .downTime(baseTime + 60)
2300 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002301 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002302 .build()));
2303 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2304
2305 // release tap
2306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002307 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2309 AINPUT_SOURCE_TOUCHSCREEN)
2310 .deviceId(touchDeviceId)
2311 .downTime(baseTime + 60)
2312 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 .build()));
2315 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2316
2317 // No more events
2318 leftWindow->assertNoEvents();
2319 rightWindow->assertNoEvents();
2320}
2321
2322/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002323 * Start hovering in a window. While this hover is still active, make another window appear on top.
2324 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2325 * While the top window is present, the hovering is stopped.
2326 * Later, hovering gets resumed again.
2327 * Ensure that new hover gesture is handled correctly.
2328 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2329 * to the window that's currently being hovered over.
2330 */
2331TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2332 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2333 sp<FakeWindowHandle> window =
2334 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2335 window->setFrame(Rect(0, 0, 200, 200));
2336
2337 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002338 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002339
2340 // Start hovering in the window
2341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2342 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2343 .build());
2344 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2345
2346 // Now, an obscuring window appears!
2347 sp<FakeWindowHandle> obscuringWindow =
2348 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2349 ADISPLAY_ID_DEFAULT,
2350 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2351 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2352 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2353 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2354 obscuringWindow->setNoInputChannel(true);
2355 obscuringWindow->setFocusable(false);
2356 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002357 mDispatcher->onWindowInfosChanged(
2358 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002359
2360 // While this new obscuring window is present, the hovering is stopped
2361 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2362 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2363 .build());
2364 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2365
2366 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002367 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002368
2369 // And a new hover gesture starts.
2370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2371 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2372 .build());
2373 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2374}
2375
2376/**
2377 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2378 * the obscuring window.
2379 */
2380TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2381 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2382 sp<FakeWindowHandle> window =
2383 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2384 window->setFrame(Rect(0, 0, 200, 200));
2385
2386 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002387 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002388
2389 // Start hovering in the window
2390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2391 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2392 .build());
2393 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2394
2395 // Now, an obscuring window appears!
2396 sp<FakeWindowHandle> obscuringWindow =
2397 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2398 ADISPLAY_ID_DEFAULT,
2399 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2400 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2401 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2402 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2403 obscuringWindow->setNoInputChannel(true);
2404 obscuringWindow->setFocusable(false);
2405 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002406 mDispatcher->onWindowInfosChanged(
2407 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002408
2409 // While this new obscuring window is present, the hovering continues. The event can't go to the
2410 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2412 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2413 .build());
2414 obscuringWindow->assertNoEvents();
2415 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2416
2417 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002419
2420 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2421 // so it should generate a HOVER_ENTER
2422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2424 .build());
2425 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2426
2427 // Now the MOVE should be getting dispatched normally
2428 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2429 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2430 .build());
2431 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2432}
2433
2434/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002435 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2436 * events are delivered to the window.
2437 */
2438TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2440 sp<FakeWindowHandle> window =
2441 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2442 window->setFrame(Rect(0, 0, 200, 200));
2443 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2444
2445 // Start hovering in the window
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2447 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2448 .build());
2449 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2450
2451 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2452 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2453 .build());
2454 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2455
2456 // Scroll with the mouse
2457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2458 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2459 .build());
2460 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2461}
2462
2463using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2464
2465/**
2466 * One window. Stylus down on the window. Next, touch from another device goes down.
2467 */
2468TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2470 sp<FakeWindowHandle> window =
2471 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2472 window->setFrame(Rect(0, 0, 200, 200));
2473
2474 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2475
2476 constexpr int32_t touchDeviceId = 4;
2477 constexpr int32_t stylusDeviceId = 2;
2478
2479 // Stylus down
2480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2481 .deviceId(stylusDeviceId)
2482 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2483 .build());
2484 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2485
2486 // Touch down
2487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2488 .deviceId(touchDeviceId)
2489 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2490 .build());
2491 // Touch cancels stylus
2492 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2493 WithCoords(100, 110)));
2494 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2495 WithCoords(140, 145)));
2496
2497 // Touch move
2498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2499 .deviceId(touchDeviceId)
2500 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2501 .build());
2502 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2503 WithCoords(141, 146)));
2504
2505 // Subsequent stylus movements are dropped
2506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2507 .deviceId(stylusDeviceId)
2508 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2509 .build());
2510 window->assertNoEvents();
2511}
2512
2513/**
2514 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2515 * down.
2516 * Similar test as above, but with added SPY window.
2517 */
2518TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
2519 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2520 sp<FakeWindowHandle> window =
2521 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2522 sp<FakeWindowHandle> spyWindow =
2523 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2524 spyWindow->setFrame(Rect(0, 0, 200, 200));
2525 spyWindow->setTrustedOverlay(true);
2526 spyWindow->setSpy(true);
2527 window->setFrame(Rect(0, 0, 200, 200));
2528
2529 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2530
2531 constexpr int32_t touchDeviceId = 4;
2532 constexpr int32_t stylusDeviceId = 2;
2533
2534 // Stylus down
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2536 .deviceId(stylusDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2538 .build());
2539 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2540 spyWindow->consumeMotionEvent(
2541 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2542
2543 // Touch down
2544 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2545 .deviceId(touchDeviceId)
2546 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2547 .build());
2548
2549 // Touch move
2550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2551 .deviceId(touchDeviceId)
2552 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2553 .build());
2554 window->consumeMotionEvent(
2555 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2556 spyWindow->consumeMotionEvent(
2557 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2558 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2559 spyWindow->consumeMotionEvent(
2560 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2561 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2562 spyWindow->consumeMotionEvent(
2563 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2564 // Subsequent stylus movements are dropped
2565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2566 .deviceId(stylusDeviceId)
2567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2568 .build());
2569
2570 window->assertNoEvents();
2571 spyWindow->assertNoEvents();
2572}
2573
2574/**
2575 * One window. Stylus hover on the window. Next, touch from another device goes down.
2576 */
2577TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2579 sp<FakeWindowHandle> window =
2580 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2581 window->setFrame(Rect(0, 0, 200, 200));
2582
2583 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2584
2585 constexpr int32_t touchDeviceId = 4;
2586 constexpr int32_t stylusDeviceId = 2;
2587
2588 // Stylus down on the window
2589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2590 .deviceId(stylusDeviceId)
2591 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2592 .build());
2593 window->consumeMotionEvent(
2594 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2595
2596 // Touch down on window
2597 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2598 .deviceId(touchDeviceId)
2599 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2600 .build());
2601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2602 .deviceId(touchDeviceId)
2603 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2604 .build());
2605 window->consumeMotionEvent(
2606 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2607 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2608 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2609 // Subsequent stylus movements are ignored
2610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2611 .deviceId(stylusDeviceId)
2612 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2613 .build());
2614 window->assertNoEvents();
2615}
2616
2617/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002618 * Two windows: a window on the left and a window on the right.
2619 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2620 * down. Then, on the left window, also place second touch pointer down.
2621 * This test tries to reproduce a crash.
2622 * In the buggy implementation, second pointer down on the left window would cause a crash.
2623 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002624TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2626 sp<FakeWindowHandle> leftWindow =
2627 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2628 leftWindow->setFrame(Rect(0, 0, 200, 200));
2629
2630 sp<FakeWindowHandle> rightWindow =
2631 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2632 rightWindow->setFrame(Rect(200, 0, 400, 200));
2633
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002634 mDispatcher->onWindowInfosChanged(
2635 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002636
2637 const int32_t touchDeviceId = 4;
2638 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002639
2640 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2642 .deviceId(mouseDeviceId)
2643 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2644 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002645 leftWindow->consumeMotionEvent(
2646 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2647
2648 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2650 .deviceId(mouseDeviceId)
2651 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2652 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002654
2655 leftWindow->consumeMotionEvent(
2656 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2657 leftWindow->consumeMotionEvent(
2658 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2659
Prabir Pradhan678438e2023-04-13 19:32:51 +00002660 mDispatcher->notifyMotion(
2661 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2662 .deviceId(mouseDeviceId)
2663 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2664 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2665 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2666 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002667 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2668
2669 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2671 .deviceId(touchDeviceId)
2672 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2673 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002674 leftWindow->consumeMotionEvent(
2675 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002676 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2677
2678 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002679 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2680 .deviceId(touchDeviceId)
2681 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2682 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2683 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002684 leftWindow->consumeMotionEvent(
2685 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2686 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2687 // current implementation.
2688 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2689 rightWindow->consumeMotionEvent(
2690 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2691
2692 leftWindow->assertNoEvents();
2693 rightWindow->assertNoEvents();
2694}
2695
2696/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002697 * Two windows: a window on the left and a window on the right.
2698 * Mouse is hovered on the left window and stylus is hovered on the right window.
2699 */
2700TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2701 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2702 sp<FakeWindowHandle> leftWindow =
2703 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2704 leftWindow->setFrame(Rect(0, 0, 200, 200));
2705
2706 sp<FakeWindowHandle> rightWindow =
2707 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2708 rightWindow->setFrame(Rect(200, 0, 400, 200));
2709
2710 mDispatcher->onWindowInfosChanged(
2711 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2712
2713 const int32_t stylusDeviceId = 3;
2714 const int32_t mouseDeviceId = 6;
2715
2716 // Start hovering over the left window
2717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2718 .deviceId(mouseDeviceId)
2719 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2720 .build());
2721 leftWindow->consumeMotionEvent(
2722 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2723
2724 // Stylus hovered on right window
2725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2726 .deviceId(stylusDeviceId)
2727 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2728 .build());
2729 leftWindow->consumeMotionEvent(
2730 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2731 rightWindow->consumeMotionEvent(
2732 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2733
2734 // Subsequent HOVER_MOVE events are dispatched correctly.
2735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2736 .deviceId(mouseDeviceId)
2737 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2738 .build());
2739 leftWindow->consumeMotionEvent(
2740 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2741 rightWindow->consumeMotionEvent(
2742 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2743
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2745 .deviceId(stylusDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2747 .build());
2748 leftWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2750 rightWindow->consumeMotionEvent(
2751 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2752
2753 leftWindow->assertNoEvents();
2754 rightWindow->assertNoEvents();
2755}
2756
2757/**
2758 * Three windows: a window on the left and a window on the right.
2759 * And a spy window that's positioned above all of them.
2760 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2761 * Check the stream that's received by the spy.
2762 */
2763TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2765
2766 sp<FakeWindowHandle> spyWindow =
2767 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2768 spyWindow->setFrame(Rect(0, 0, 400, 400));
2769 spyWindow->setTrustedOverlay(true);
2770 spyWindow->setSpy(true);
2771
2772 sp<FakeWindowHandle> leftWindow =
2773 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2774 leftWindow->setFrame(Rect(0, 0, 200, 200));
2775
2776 sp<FakeWindowHandle> rightWindow =
2777 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2778
2779 rightWindow->setFrame(Rect(200, 0, 400, 200));
2780
2781 mDispatcher->onWindowInfosChanged(
2782 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2783
2784 const int32_t stylusDeviceId = 1;
2785 const int32_t touchDeviceId = 2;
2786
2787 // Stylus down on the left window
2788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2789 .deviceId(stylusDeviceId)
2790 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2791 .build());
2792 leftWindow->consumeMotionEvent(
2793 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2794 spyWindow->consumeMotionEvent(
2795 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2796
2797 // Touch down on the right window
2798 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2799 .deviceId(touchDeviceId)
2800 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2801 .build());
2802 leftWindow->consumeMotionEvent(
2803 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2804 spyWindow->consumeMotionEvent(
2805 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2806 rightWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2808 spyWindow->consumeMotionEvent(
2809 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2810
2811 // Stylus movements continue, but are ignored because the touch went down more recently.
2812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2813 .deviceId(stylusDeviceId)
2814 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2815 .build());
2816
2817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2818 .deviceId(touchDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2820 .build());
2821 rightWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2823 spyWindow->consumeMotionEvent(
2824 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2825
2826 spyWindow->assertNoEvents();
2827 leftWindow->assertNoEvents();
2828 rightWindow->assertNoEvents();
2829}
2830
2831/**
2832 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2833 * both.
2834 * Check hover in left window and touch down in the right window.
2835 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2836 */
2837TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2839
2840 sp<FakeWindowHandle> spyWindow =
2841 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2842 spyWindow->setFrame(Rect(0, 0, 400, 400));
2843 spyWindow->setTrustedOverlay(true);
2844 spyWindow->setSpy(true);
2845
2846 sp<FakeWindowHandle> leftWindow =
2847 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2848 leftWindow->setFrame(Rect(0, 0, 200, 200));
2849
2850 sp<FakeWindowHandle> rightWindow =
2851 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2852 rightWindow->setFrame(Rect(200, 0, 400, 200));
2853
2854 mDispatcher->onWindowInfosChanged(
2855 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2856
2857 const int32_t stylusDeviceId = 1;
2858 const int32_t touchDeviceId = 2;
2859
2860 // Stylus hover on the left window
2861 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2862 .deviceId(stylusDeviceId)
2863 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2864 .build());
2865 leftWindow->consumeMotionEvent(
2866 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2867 spyWindow->consumeMotionEvent(
2868 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2869
2870 // Touch down on the right window.
2871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2872 .deviceId(touchDeviceId)
2873 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2874 .build());
2875 leftWindow->consumeMotionEvent(
2876 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2877 spyWindow->consumeMotionEvent(
2878 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2879 spyWindow->consumeMotionEvent(
2880 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2881 rightWindow->consumeMotionEvent(
2882 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2883
2884 // Stylus movements continue, but are ignored because the touch is down.
2885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2886 .deviceId(stylusDeviceId)
2887 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2888 .build());
2889
2890 // Touch movements continue. They should be delivered to the right window and to the spy
2891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2892 .deviceId(touchDeviceId)
2893 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2894 .build());
2895 spyWindow->consumeMotionEvent(
2896 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2897 rightWindow->consumeMotionEvent(
2898 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2899
2900 spyWindow->assertNoEvents();
2901 leftWindow->assertNoEvents();
2902 rightWindow->assertNoEvents();
2903}
2904
2905/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002906 * On a single window, use two different devices: mouse and touch.
2907 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2908 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2909 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2910 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2911 * represent a new gesture.
2912 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002913TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2915 sp<FakeWindowHandle> window =
2916 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2917 window->setFrame(Rect(0, 0, 400, 400));
2918
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002919 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002920
2921 const int32_t touchDeviceId = 4;
2922 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002923
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002924 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2926 .deviceId(touchDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2928 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002929 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002930 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2931 .deviceId(touchDeviceId)
2932 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2933 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2934 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002935 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002936 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2937 .deviceId(touchDeviceId)
2938 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2939 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2940 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002941 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2942 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2943 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2944
2945 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002946 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2947 .deviceId(mouseDeviceId)
2948 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2950 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002951
2952 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002953 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002954 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2955
Prabir Pradhan678438e2023-04-13 19:32:51 +00002956 mDispatcher->notifyMotion(
2957 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2958 .deviceId(mouseDeviceId)
2959 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2960 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2961 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2962 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002963 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2964
2965 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002966 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2967 .deviceId(touchDeviceId)
2968 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2969 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2970 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002971 // Since we already canceled this touch gesture, it will be ignored until a completely new
2972 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2973 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2974 // However, mouse movements should continue to work.
2975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2976 .deviceId(mouseDeviceId)
2977 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2978 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2979 .build());
2980 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2981
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002982 window->assertNoEvents();
2983}
2984
2985/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002986 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2987 * the injected event.
2988 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002989TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002990 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2991 sp<FakeWindowHandle> window =
2992 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2993 window->setFrame(Rect(0, 0, 400, 400));
2994
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002995 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002996
2997 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002998 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2999 // completion.
3000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003001 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003002 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3003 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003004 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003005 .build()));
3006 window->consumeMotionEvent(
3007 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3008
3009 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3010 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003011 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3012 .deviceId(touchDeviceId)
3013 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3014 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003015
3016 window->consumeMotionEvent(
3017 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3018 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3019}
3020
3021/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003022 * This test is similar to the test above, but the sequence of injected events is different.
3023 *
3024 * Two windows: a window on the left and a window on the right.
3025 * Mouse is hovered over the left window.
3026 * Next, we tap on the left window, where the cursor was last seen.
3027 *
3028 * After that, we inject one finger down onto the right window, and then a second finger down onto
3029 * the left window.
3030 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3031 * window (first), and then another on the left window (second).
3032 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3033 * In the buggy implementation, second finger down on the left window would cause a crash.
3034 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003035TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3037 sp<FakeWindowHandle> leftWindow =
3038 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3039 leftWindow->setFrame(Rect(0, 0, 200, 200));
3040
3041 sp<FakeWindowHandle> rightWindow =
3042 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3043 rightWindow->setFrame(Rect(200, 0, 400, 200));
3044
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003045 mDispatcher->onWindowInfosChanged(
3046 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003047
3048 const int32_t mouseDeviceId = 6;
3049 const int32_t touchDeviceId = 4;
3050 // Hover over the left window. Keep the cursor there.
3051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003052 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003053 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3054 AINPUT_SOURCE_MOUSE)
3055 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003056 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003057 .build()));
3058 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3059
3060 // Tap on left window
3061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003062 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003063 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3064 AINPUT_SOURCE_TOUCHSCREEN)
3065 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003066 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003067 .build()));
3068
3069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003070 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003071 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3072 AINPUT_SOURCE_TOUCHSCREEN)
3073 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003074 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003075 .build()));
3076 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3077 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3078 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3079
3080 // First finger down on right window
3081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003082 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003083 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3084 AINPUT_SOURCE_TOUCHSCREEN)
3085 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003086 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003087 .build()));
3088 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3089
3090 // Second finger down on the left window
3091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003092 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003093 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3094 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003095 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3096 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003097 .build()));
3098 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3099 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3100
3101 // No more events
3102 leftWindow->assertNoEvents();
3103 rightWindow->assertNoEvents();
3104}
3105
3106/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003107 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3108 * While the touch is down, new hover events from the stylus device should be ignored. After the
3109 * touch is gone, stylus hovering should start working again.
3110 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003111TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3113 sp<FakeWindowHandle> window =
3114 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3115 window->setFrame(Rect(0, 0, 200, 200));
3116
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003117 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003118
3119 const int32_t stylusDeviceId = 5;
3120 const int32_t touchDeviceId = 4;
3121 // Start hovering with stylus
3122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003123 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003124 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003125 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003126 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003127 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003128 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003129
3130 // Finger down on the window
3131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003132 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003133 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003134 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003135 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003136 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003137 window->consumeMotionEvent(
3138 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3139 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003140
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003141 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003142 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003143 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003144 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3145 AINPUT_SOURCE_STYLUS)
3146 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003147 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003148 .build()));
3149 // No event should be sent. This event should be ignored because a pointer from another device
3150 // is already down.
3151
3152 // Lift up the finger
3153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003154 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003155 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3156 AINPUT_SOURCE_TOUCHSCREEN)
3157 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003158 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003159 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003160 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003161
3162 // Now that the touch is gone, stylus hovering should start working again
3163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003164 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003165 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3166 AINPUT_SOURCE_STYLUS)
3167 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003168 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003169 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003170 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3171 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003172 window->assertNoEvents();
3173}
3174
3175/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003176 * A spy window above a window with no input channel.
3177 * Start hovering with a stylus device, and then tap with it.
3178 * Ensure spy window receives the entire sequence.
3179 */
3180TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3182 sp<FakeWindowHandle> spyWindow =
3183 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3184 spyWindow->setFrame(Rect(0, 0, 200, 200));
3185 spyWindow->setTrustedOverlay(true);
3186 spyWindow->setSpy(true);
3187 sp<FakeWindowHandle> window =
3188 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3189 window->setNoInputChannel(true);
3190 window->setFrame(Rect(0, 0, 200, 200));
3191
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003192 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003193
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003194 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003195 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3196 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3197 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003198 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3199 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003200 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3201 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3202 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003203 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3204
3205 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3207 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3208 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003209 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3210
3211 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3213 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3214 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003215 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3216
3217 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003218 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3219 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3220 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003221 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3222 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003223 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3224 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3225 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003226 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3227
3228 // No more events
3229 spyWindow->assertNoEvents();
3230 window->assertNoEvents();
3231}
3232
3233/**
3234 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3235 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3236 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3237 * While the mouse is down, new move events from the touch device should be ignored.
3238 */
3239TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3240 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3241 sp<FakeWindowHandle> spyWindow =
3242 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3243 spyWindow->setFrame(Rect(0, 0, 200, 200));
3244 spyWindow->setTrustedOverlay(true);
3245 spyWindow->setSpy(true);
3246 sp<FakeWindowHandle> window =
3247 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3248 window->setFrame(Rect(0, 0, 200, 200));
3249
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003250 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003251
3252 const int32_t mouseDeviceId = 7;
3253 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003254
3255 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003256 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3257 .deviceId(mouseDeviceId)
3258 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3259 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003260 spyWindow->consumeMotionEvent(
3261 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3262 window->consumeMotionEvent(
3263 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3264
3265 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003266 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3267 .deviceId(touchDeviceId)
3268 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3269 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003270 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3271 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3272 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3273 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3274
Prabir Pradhan678438e2023-04-13 19:32:51 +00003275 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3276 .deviceId(touchDeviceId)
3277 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3278 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003279 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3280 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3281
3282 // Pilfer the stream
3283 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3284 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3285
Prabir Pradhan678438e2023-04-13 19:32:51 +00003286 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3287 .deviceId(touchDeviceId)
3288 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3289 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003290 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3291
3292 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003293 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3294 .deviceId(mouseDeviceId)
3295 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3296 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3297 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003298
3299 spyWindow->consumeMotionEvent(
3300 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3301 spyWindow->consumeMotionEvent(
3302 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3303 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3304
Prabir Pradhan678438e2023-04-13 19:32:51 +00003305 mDispatcher->notifyMotion(
3306 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3307 .deviceId(mouseDeviceId)
3308 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3309 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3310 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3311 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003312 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3313 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3314
3315 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3317 .deviceId(mouseDeviceId)
3318 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3320 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003321 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3322 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3323
3324 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3326 .deviceId(touchDeviceId)
3327 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3328 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003329
3330 // No more events
3331 spyWindow->assertNoEvents();
3332 window->assertNoEvents();
3333}
3334
3335/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003336 * On the display, have a single window, and also an area where there's no window.
3337 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3338 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3339 */
3340TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3341 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3342 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003343 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003344
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003345 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003346
3347 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003348 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003349
3350 mDispatcher->waitForIdle();
3351 window->assertNoEvents();
3352
3353 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003354 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003355 mDispatcher->waitForIdle();
3356 window->consumeMotionDown();
3357}
3358
3359/**
3360 * Same test as above, but instead of touching the empty space, the first touch goes to
3361 * non-touchable window.
3362 */
3363TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3365 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003367 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3368 window1->setTouchable(false);
3369 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003370 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003371 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3372
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003373 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003374
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003375 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003376 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003377
3378 mDispatcher->waitForIdle();
3379 window1->assertNoEvents();
3380 window2->assertNoEvents();
3381
3382 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003383 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003384 mDispatcher->waitForIdle();
3385 window2->consumeMotionDown();
3386}
3387
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003388/**
3389 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3390 * to the event time of the first ACTION_DOWN sent to the particular window.
3391 */
3392TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3394 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003395 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003396 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3397 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003398 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003399 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3400
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003401 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003402
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003403 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003404 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003405
3406 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003407
3408 MotionEvent* motionEvent1 = window1->consumeMotion();
3409 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003410 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003411 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3412 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003413
3414 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003415 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003416 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003417 MotionEvent* motionEvent2 = window2->consumeMotion();
3418 ASSERT_NE(motionEvent2, nullptr);
3419 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003420 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003421 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003422
3423 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003424 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003425 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003426 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003427
3428 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003429 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003430 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003431 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003432
3433 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3434 window1->consumeMotionMove();
3435 window1->assertNoEvents();
3436
3437 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003438 mDispatcher->notifyMotion(
3439 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003440 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003441 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003442
Prabir Pradhan678438e2023-04-13 19:32:51 +00003443 mDispatcher->notifyMotion(
3444 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003445 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003446 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003447}
3448
Garfield Tandf26e862020-07-01 20:18:19 -07003449TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003451 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003452 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003453 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003454 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003455 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003456 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003457
3458 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3459
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003460 mDispatcher->onWindowInfosChanged(
3461 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003462
3463 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003465 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003466 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3467 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003468 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003469 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003470 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003471
3472 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003474 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003475 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3476 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003477 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003478 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003479 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3480 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003481
3482 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003484 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003485 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3486 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003487 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003488 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003489 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3490 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003491
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003493 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003494 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3495 AINPUT_SOURCE_MOUSE)
3496 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3497 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003498 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003499 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003500 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003503 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003504 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3505 AINPUT_SOURCE_MOUSE)
3506 .buttonState(0)
3507 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003508 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003509 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003510 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003511
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003513 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003514 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3515 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003516 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003517 .build()));
3518 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3519
3520 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003522 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003523 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3524 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003525 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003526 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003527 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003528
3529 // No more events
3530 windowLeft->assertNoEvents();
3531 windowRight->assertNoEvents();
3532}
3533
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003534/**
3535 * Put two fingers down (and don't release them) and click the mouse button.
3536 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3537 * currently active gesture should be canceled, and the new one should proceed.
3538 */
3539TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3541 sp<FakeWindowHandle> window =
3542 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3543 window->setFrame(Rect(0, 0, 600, 800));
3544
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003545 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003546
3547 const int32_t touchDeviceId = 4;
3548 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003549
3550 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3552 .deviceId(touchDeviceId)
3553 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3554 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003555
Prabir Pradhan678438e2023-04-13 19:32:51 +00003556 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3557 .deviceId(touchDeviceId)
3558 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3559 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3560 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003561 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3562 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3563
3564 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3566 .deviceId(mouseDeviceId)
3567 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3568 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3569 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003570 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3571 WithPointerCount(2u)));
3572 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3573
Prabir Pradhan678438e2023-04-13 19:32:51 +00003574 mDispatcher->notifyMotion(
3575 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3576 .deviceId(mouseDeviceId)
3577 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3578 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3579 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3580 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003581 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3582
3583 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3584 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3586 .deviceId(touchDeviceId)
3587 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3588 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3589 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003590 window->assertNoEvents();
3591}
3592
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003593TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3595
3596 sp<FakeWindowHandle> spyWindow =
3597 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3598 spyWindow->setFrame(Rect(0, 0, 600, 800));
3599 spyWindow->setTrustedOverlay(true);
3600 spyWindow->setSpy(true);
3601 sp<FakeWindowHandle> window =
3602 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3603 window->setFrame(Rect(0, 0, 600, 800));
3604
3605 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003606 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003607
3608 // Send mouse cursor to the window
3609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003610 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003611 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3612 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003613 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003614 .build()));
3615
3616 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3617 WithSource(AINPUT_SOURCE_MOUSE)));
3618 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3619 WithSource(AINPUT_SOURCE_MOUSE)));
3620
3621 window->assertNoEvents();
3622 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003623}
3624
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003625TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3627
3628 sp<FakeWindowHandle> spyWindow =
3629 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3630 spyWindow->setFrame(Rect(0, 0, 600, 800));
3631 spyWindow->setTrustedOverlay(true);
3632 spyWindow->setSpy(true);
3633 sp<FakeWindowHandle> window =
3634 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3635 window->setFrame(Rect(0, 0, 600, 800));
3636
3637 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003638 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003639
3640 // Send mouse cursor to the window
3641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003642 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003643 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3644 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003645 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003646 .build()));
3647
3648 // Move mouse cursor
3649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003650 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003651 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3652 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003653 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003654 .build()));
3655
3656 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3657 WithSource(AINPUT_SOURCE_MOUSE)));
3658 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3659 WithSource(AINPUT_SOURCE_MOUSE)));
3660 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3661 WithSource(AINPUT_SOURCE_MOUSE)));
3662 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3663 WithSource(AINPUT_SOURCE_MOUSE)));
3664 // Touch down on the window
3665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003666 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003667 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3668 AINPUT_SOURCE_TOUCHSCREEN)
3669 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003670 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003671 .build()));
3672 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3673 WithSource(AINPUT_SOURCE_MOUSE)));
3674 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3675 WithSource(AINPUT_SOURCE_MOUSE)));
3676 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3677 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3678 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3679 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3680
3681 // pilfer the motion, retaining the gesture on the spy window.
3682 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3683 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3684 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3685
3686 // Touch UP on the window
3687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003688 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003689 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3690 AINPUT_SOURCE_TOUCHSCREEN)
3691 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003692 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003693 .build()));
3694 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3695 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3696
3697 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3698 // to send a new gesture. It should again go to both windows (spy and the window below), just
3699 // like the first gesture did, before pilfering. The window configuration has not changed.
3700
3701 // One more tap - DOWN
3702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003703 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003704 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3705 AINPUT_SOURCE_TOUCHSCREEN)
3706 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003707 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003708 .build()));
3709 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3710 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3711 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3712 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3713
3714 // Touch UP on the window
3715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003716 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003717 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3718 AINPUT_SOURCE_TOUCHSCREEN)
3719 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003720 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003721 .build()));
3722 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3723 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3724 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3725 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3726
3727 window->assertNoEvents();
3728 spyWindow->assertNoEvents();
3729}
3730
Garfield Tandf26e862020-07-01 20:18:19 -07003731// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3732// directly in this test.
3733TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003734 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003735 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003736 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003737 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003738
3739 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3740
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003741 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003742
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003744 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003745 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3746 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003747 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003748 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003749 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003750 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003752 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003753 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3754 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003755 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003756 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003757 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3758 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003759
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003761 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003762 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3763 AINPUT_SOURCE_MOUSE)
3764 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3765 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003766 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003767 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003768 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003769
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003771 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003772 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3773 AINPUT_SOURCE_MOUSE)
3774 .buttonState(0)
3775 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003776 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003777 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003778 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003779
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003781 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003782 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3783 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003784 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003785 .build()));
3786 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3787
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003788 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3789 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3790 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003791 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003792 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3793 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003794 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003795 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003796 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003797}
3798
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003799/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003800 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3801 * is generated.
3802 */
3803TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3805 sp<FakeWindowHandle> window =
3806 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3807 window->setFrame(Rect(0, 0, 1200, 800));
3808
3809 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3810
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003811 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003812
3813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003814 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003815 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3816 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003817 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003818 .build()));
3819 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3820
3821 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003822 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003823 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3824}
3825
3826/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003827 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3828 */
3829TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3831 sp<FakeWindowHandle> window =
3832 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3833 window->setFrame(Rect(0, 0, 1200, 800));
3834
3835 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3836
3837 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3838
3839 MotionEventBuilder hoverEnterBuilder =
3840 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3842 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3844 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3846 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3847 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3848 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3849}
3850
3851/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003852 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3853 */
3854TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3856 sp<FakeWindowHandle> window =
3857 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3858 window->setFrame(Rect(0, 0, 100, 100));
3859
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003860 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003861
3862 const int32_t mouseDeviceId = 7;
3863 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003864
3865 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003866 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3867 .deviceId(mouseDeviceId)
3868 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3869 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003870 window->consumeMotionEvent(
3871 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3872
3873 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3875 .deviceId(touchDeviceId)
3876 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3877 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003878
3879 window->consumeMotionEvent(
3880 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3881 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3882}
3883
3884/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003885 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003886 * The tap causes a HOVER_EXIT event to be generated because the current event
3887 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003888 */
3889TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3891 sp<FakeWindowHandle> window =
3892 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3893 window->setFrame(Rect(0, 0, 100, 100));
3894
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003895 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003896 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3897 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3898 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003899 ASSERT_NO_FATAL_FAILURE(
3900 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3901 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003902
3903 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3905 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3906 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003907 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003908 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3909 WithSource(AINPUT_SOURCE_MOUSE))));
3910
3911 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003912 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3913 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3914
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3916 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3917 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003918 ASSERT_NO_FATAL_FAILURE(
3919 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3920 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3921}
3922
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003923TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3925 sp<FakeWindowHandle> windowDefaultDisplay =
3926 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3927 ADISPLAY_ID_DEFAULT);
3928 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3929 sp<FakeWindowHandle> windowSecondDisplay =
3930 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3931 SECOND_DISPLAY_ID);
3932 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3933
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003934 mDispatcher->onWindowInfosChanged(
3935 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003936
3937 // Set cursor position in window in default display and check that hover enter and move
3938 // events are generated.
3939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003940 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003941 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3942 AINPUT_SOURCE_MOUSE)
3943 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003944 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003945 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003946 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003947
3948 // Remove all windows in secondary display and check that no event happens on window in
3949 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003950 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3951
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003952 windowDefaultDisplay->assertNoEvents();
3953
3954 // Move cursor position in window in default display and check that only hover move
3955 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003956 mDispatcher->onWindowInfosChanged(
3957 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003959 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003960 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3961 AINPUT_SOURCE_MOUSE)
3962 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003963 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003964 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003965 windowDefaultDisplay->consumeMotionEvent(
3966 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3967 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003968 windowDefaultDisplay->assertNoEvents();
3969}
3970
Garfield Tan00f511d2019-06-12 16:55:40 -07003971TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003973
3974 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003975 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003976 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003977 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003978 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003979 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003980
3981 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3982
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003983 mDispatcher->onWindowInfosChanged(
3984 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003985
3986 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3987 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003989 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003990 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003991 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003992 windowRight->assertNoEvents();
3993}
3994
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003995TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003996 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003997 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3998 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003999 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004000
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004001 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004002 setFocusedWindow(window);
4003
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004004 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004005
Prabir Pradhan678438e2023-04-13 19:32:51 +00004006 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004007
4008 // Window should receive key down event.
4009 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4010
4011 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4012 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004013 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004014 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004015 AKEY_EVENT_FLAG_CANCELED);
4016}
4017
4018TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004020 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4021 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004022
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004023 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004024
Prabir Pradhan678438e2023-04-13 19:32:51 +00004025 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4026 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004027
4028 // Window should receive motion down event.
4029 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4030
4031 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4032 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004033 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004034 window->consumeMotionEvent(
4035 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004036}
4037
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004038TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4039 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4040 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4041 "Fake Window", ADISPLAY_ID_DEFAULT);
4042
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004043 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004044
4045 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4046 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4047 .build());
4048
4049 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4050
4051 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4052 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4053 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4054
4055 // After the device has been reset, a new hovering stream can be sent to the window
4056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4057 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4058 .build());
4059 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4060}
4061
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004062TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4063 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004064 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4065 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004066 window->setFocusable(true);
4067
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004068 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004069 setFocusedWindow(window);
4070
4071 window->consumeFocusEvent(true);
4072
Prabir Pradhan678438e2023-04-13 19:32:51 +00004073 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004074 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4075 const nsecs_t injectTime = keyArgs.eventTime;
4076 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004077 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004078 // The dispatching time should be always greater than or equal to intercept key timeout.
4079 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4080 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4081 std::chrono::nanoseconds(interceptKeyTimeout).count());
4082}
4083
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004084/**
4085 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4086 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004087TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004089 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4090 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004091 window->setFocusable(true);
4092
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004093 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004094 setFocusedWindow(window);
4095
4096 window->consumeFocusEvent(true);
4097
Prabir Pradhan678438e2023-04-13 19:32:51 +00004098 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004099 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004100
4101 // Set a value that's significantly larger than the default consumption timeout. If the
4102 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4103 mFakePolicy->setInterceptKeyTimeout(600ms);
4104 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4105 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004106 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4107}
4108
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004109/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004110 * Two windows. First is a regular window. Second does not overlap with the first, and has
4111 * WATCH_OUTSIDE_TOUCH.
4112 * Both windows are owned by the same UID.
4113 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4114 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4115 */
4116TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4117 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004118 sp<FakeWindowHandle> window =
4119 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004120 window->setFrame(Rect{0, 0, 100, 100});
4121
4122 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004123 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004124 ADISPLAY_ID_DEFAULT);
4125 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4126 outsideWindow->setWatchOutsideTouch(true);
4127 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004128 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004129
4130 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004131 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4132 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4133 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004134 window->consumeMotionDown();
4135 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4136 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4137 outsideWindow->consumeMotionEvent(
4138 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4139}
4140
4141/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004142 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4143 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4144 * ACTION_OUTSIDE event is sent per gesture.
4145 */
4146TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4147 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004149 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4150 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004151 window->setWatchOutsideTouch(true);
4152 window->setFrame(Rect{0, 0, 100, 100});
4153 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004154 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4155 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004156 secondWindow->setFrame(Rect{100, 100, 200, 200});
4157 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004158 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4159 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004160 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004161 mDispatcher->onWindowInfosChanged(
4162 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004163
4164 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004165 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4166 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4167 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004168 window->assertNoEvents();
4169 secondWindow->assertNoEvents();
4170
4171 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4172 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004173 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4174 ADISPLAY_ID_DEFAULT,
4175 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004176 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4177 window->consumeMotionEvent(
4178 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004179 secondWindow->consumeMotionDown();
4180 thirdWindow->assertNoEvents();
4181
4182 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4183 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004184 mDispatcher->notifyMotion(
4185 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4186 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004187 window->assertNoEvents();
4188 secondWindow->consumeMotionMove();
4189 thirdWindow->consumeMotionDown();
4190}
4191
Prabir Pradhan814fe082022-07-22 20:22:18 +00004192TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004194 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4195 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004196 window->setFocusable(true);
4197
Patrick Williamsd828f302023-04-28 17:52:08 -05004198 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004199 setFocusedWindow(window);
4200
4201 window->consumeFocusEvent(true);
4202
Prabir Pradhan678438e2023-04-13 19:32:51 +00004203 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4204 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4205 mDispatcher->notifyKey(keyDown);
4206 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004207
4208 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4209 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4210
4211 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004212 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004213
4214 window->consumeFocusEvent(false);
4215
Prabir Pradhan678438e2023-04-13 19:32:51 +00004216 mDispatcher->notifyKey(keyDown);
4217 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004218 window->assertNoEvents();
4219}
4220
Arthur Hung96483742022-11-15 03:30:48 +00004221TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4223 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4224 "Fake Window", ADISPLAY_ID_DEFAULT);
4225 // Ensure window is non-split and have some transform.
4226 window->setPreventSplitting(true);
4227 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004228 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004229
4230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004231 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004232 {50, 50}))
4233 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4234 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4235
4236 const MotionEvent secondFingerDownEvent =
4237 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4238 .displayId(ADISPLAY_ID_DEFAULT)
4239 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004240 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4241 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004242 .build();
4243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004244 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004245 InputEventInjectionSync::WAIT_FOR_RESULT))
4246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4247
4248 const MotionEvent* event = window->consumeMotion();
4249 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4250 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4251 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4252 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4253 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4254}
4255
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004256/**
4257 * Two windows: a splittable and a non-splittable.
4258 * The non-splittable window shouldn't receive any "incomplete" gestures.
4259 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4260 * The second pointer should be dropped because the initial window is splittable, so it won't get
4261 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4262 * "incomplete" gestures.
4263 */
4264TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4266 sp<FakeWindowHandle> leftWindow =
4267 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4268 ADISPLAY_ID_DEFAULT);
4269 leftWindow->setPreventSplitting(false);
4270 leftWindow->setFrame(Rect(0, 0, 100, 100));
4271 sp<FakeWindowHandle> rightWindow =
4272 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4273 ADISPLAY_ID_DEFAULT);
4274 rightWindow->setPreventSplitting(true);
4275 rightWindow->setFrame(Rect(100, 100, 200, 200));
4276 mDispatcher->onWindowInfosChanged(
4277 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4278
4279 // Touch down on left, splittable window
4280 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4281 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4282 .build());
4283 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4284
4285 mDispatcher->notifyMotion(
4286 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4287 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4288 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4289 .build());
4290 leftWindow->assertNoEvents();
4291 rightWindow->assertNoEvents();
4292}
4293
Harry Cuttsb166c002023-05-09 13:06:05 +00004294TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4295 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4296 sp<FakeWindowHandle> window =
4297 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4298 window->setFrame(Rect(0, 0, 400, 400));
4299 sp<FakeWindowHandle> trustedOverlay =
4300 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4301 ADISPLAY_ID_DEFAULT);
4302 trustedOverlay->setSpy(true);
4303 trustedOverlay->setTrustedOverlay(true);
4304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004305 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004306
4307 // Start a three-finger touchpad swipe
4308 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4309 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4310 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4311 .build());
4312 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4313 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4314 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4315 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4316 .build());
4317 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4318 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4319 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4320 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4321 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4322 .build());
4323
4324 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4325 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4326 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4327
4328 // Move the swipe a bit
4329 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4330 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4331 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4332 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4333 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4334 .build());
4335
4336 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4337
4338 // End the swipe
4339 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4340 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4341 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4342 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4343 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4344 .build());
4345 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4346 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4347 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4348 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4349 .build());
4350 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4351 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4352 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4353 .build());
4354
4355 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4356 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4357 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4358
4359 window->assertNoEvents();
4360}
4361
4362TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4364 sp<FakeWindowHandle> window =
4365 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4366 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004367 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004368
4369 // Start a three-finger touchpad swipe
4370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4371 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4372 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4373 .build());
4374 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4375 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4376 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4377 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4378 .build());
4379 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4380 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4381 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4382 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4383 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4384 .build());
4385
4386 // Move the swipe a bit
4387 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4388 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4389 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4390 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4391 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4392 .build());
4393
4394 // End the swipe
4395 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4396 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4397 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4398 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4399 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4400 .build());
4401 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4402 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4403 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4404 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4405 .build());
4406 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4407 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4408 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4409 .build());
4410
4411 window->assertNoEvents();
4412}
4413
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004414/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004415 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4416 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004417 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004418 */
4419TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4421 sp<FakeWindowHandle> window =
4422 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4423 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004424 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004425
4426 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4428 .downTime(baseTime + 10)
4429 .eventTime(baseTime + 10)
4430 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4431 .build());
4432
4433 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4434
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004435 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004436 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004437
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004438 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004439
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004440 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4441 .downTime(baseTime + 10)
4442 .eventTime(baseTime + 30)
4443 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4444 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4445 .build());
4446
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004447 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4448
4449 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004450 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4451 .downTime(baseTime + 10)
4452 .eventTime(baseTime + 40)
4453 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4454 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4455 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004456
4457 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4458
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4460 .downTime(baseTime + 10)
4461 .eventTime(baseTime + 50)
4462 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4463 .build());
4464
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004465 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4466
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4468 .downTime(baseTime + 60)
4469 .eventTime(baseTime + 60)
4470 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4471 .build());
4472
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004473 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004474}
4475
4476/**
Hu Guo771a7692023-09-17 20:51:08 +08004477 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4478 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4479 * its coordinates should be converted by the transform of the windows of target screen.
4480 */
4481TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4482 // This case will create a window and a spy window on the default display and mirror
4483 // window on the second display. cancel event is sent through spy window pilferPointers
4484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4485
4486 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4487 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4488 spyWindowDefaultDisplay->setTrustedOverlay(true);
4489 spyWindowDefaultDisplay->setSpy(true);
4490
4491 sp<FakeWindowHandle> windowDefaultDisplay =
4492 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4493 ADISPLAY_ID_DEFAULT);
4494 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4495
4496 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4497 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4498
4499 // Add the windows to the dispatcher
4500 mDispatcher->onWindowInfosChanged(
4501 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4502 *windowSecondDisplay->getInfo()},
4503 {},
4504 0,
4505 0});
4506
4507 // Send down to ADISPLAY_ID_DEFAULT
4508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4509 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4510 {100, 100}))
4511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4512
4513 spyWindowDefaultDisplay->consumeMotionDown();
4514 windowDefaultDisplay->consumeMotionDown();
4515
4516 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4517
4518 // windowDefaultDisplay gets cancel
4519 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4520 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4521
4522 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4523 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4524 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4525 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4526 EXPECT_EQ(100, event->getX(0));
4527 EXPECT_EQ(100, event->getY(0));
4528}
4529
4530/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004531 * Ensure the correct coordinate spaces are used by InputDispatcher.
4532 *
4533 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4534 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4535 * space.
4536 */
4537class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4538public:
4539 void SetUp() override {
4540 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004541 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004542 }
4543
4544 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4545 gui::DisplayInfo info;
4546 info.displayId = displayId;
4547 info.transform = transform;
4548 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004549 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004550 }
4551
4552 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4553 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004554 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004555 }
4556
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004557 void removeAllWindowsAndDisplays() {
4558 mDisplayInfos.clear();
4559 mWindowInfos.clear();
4560 }
4561
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004562 // Set up a test scenario where the display has a scaled projection and there are two windows
4563 // on the display.
4564 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4565 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4566 // respectively.
4567 ui::Transform displayTransform;
4568 displayTransform.set(2, 0, 0, 4);
4569 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4570
4571 std::shared_ptr<FakeApplicationHandle> application =
4572 std::make_shared<FakeApplicationHandle>();
4573
4574 // Add two windows to the display. Their frames are represented in the display space.
4575 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004576 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4577 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004578 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4579 addWindow(firstWindow);
4580
4581 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004582 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4583 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004584 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4585 addWindow(secondWindow);
4586 return {std::move(firstWindow), std::move(secondWindow)};
4587 }
4588
4589private:
4590 std::vector<gui::DisplayInfo> mDisplayInfos;
4591 std::vector<gui::WindowInfo> mWindowInfos;
4592};
4593
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004594TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004595 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4596 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004597 // selected so that if the hit test was performed with the point and the bounds being in
4598 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004599 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4600 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4601 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004602
4603 firstWindow->consumeMotionDown();
4604 secondWindow->assertNoEvents();
4605}
4606
4607// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4608// the event should be treated as being in the logical display space.
4609TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4610 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4611 // Send down to the first window. The point is represented in the logical display space. The
4612 // point is selected so that if the hit test was done in logical display space, then it would
4613 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004614 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004615 PointF{75 * 2, 55 * 4});
4616
4617 firstWindow->consumeMotionDown();
4618 secondWindow->assertNoEvents();
4619}
4620
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004621// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4622// event should be treated as being in the logical display space.
4623TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4624 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4625
4626 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4627 ui::Transform injectedEventTransform;
4628 injectedEventTransform.set(matrix);
4629 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4630 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4631
4632 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4633 .displayId(ADISPLAY_ID_DEFAULT)
4634 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004635 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004636 .x(untransformedPoint.x)
4637 .y(untransformedPoint.y))
4638 .build();
4639 event.transform(matrix);
4640
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004641 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004642 InputEventInjectionSync::WAIT_FOR_RESULT);
4643
4644 firstWindow->consumeMotionDown();
4645 secondWindow->assertNoEvents();
4646}
4647
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004648TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4649 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4650
4651 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004652 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4653 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4654 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004655
4656 firstWindow->assertNoEvents();
4657 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004658 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004659 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4660
4661 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4662 EXPECT_EQ(300, event->getRawX(0));
4663 EXPECT_EQ(880, event->getRawY(0));
4664
4665 // Ensure that the x and y values are in the window's coordinate space.
4666 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4667 // the logical display space. This will be the origin of the window space.
4668 EXPECT_EQ(100, event->getX(0));
4669 EXPECT_EQ(80, event->getY(0));
4670}
4671
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004672TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4673 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4674 // The monitor will always receive events in the logical display's coordinate space, because
4675 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004676 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004677
4678 // Send down to the first window.
4679 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4680 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4681 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4682 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4683
4684 // Second pointer goes down on second window.
4685 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4686 ADISPLAY_ID_DEFAULT,
4687 {PointF{50, 100}, PointF{150, 220}}));
4688 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4689 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4690 {1, PointF{300, 880}}};
4691 monitor.consumeMotionEvent(
4692 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4693
4694 mDispatcher->cancelCurrentTouch();
4695
4696 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4697 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4698 monitor.consumeMotionEvent(
4699 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4700}
4701
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004702TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4703 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4704
4705 // Send down to the first window.
4706 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4707 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4708 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4709
4710 // The pointer is transferred to the second window, and the second window receives it in the
4711 // correct coordinate space.
4712 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4713 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4714 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4715}
4716
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004717/** Ensure consistent behavior of InputDispatcher in all orientations. */
4718class InputDispatcherDisplayOrientationFixture
4719 : public InputDispatcherDisplayProjectionTest,
4720 public ::testing::WithParamInterface<ui::Rotation> {};
4721
4722// This test verifies the touchable region of a window for all rotations of the display by tapping
4723// in different locations on the display, specifically points close to the four corners of a
4724// window.
4725TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4726 constexpr static int32_t displayWidth = 400;
4727 constexpr static int32_t displayHeight = 800;
4728
4729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4730
4731 const auto rotation = GetParam();
4732
4733 // Set up the display with the specified rotation.
4734 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4735 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4736 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4737 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4738 logicalDisplayWidth, logicalDisplayHeight);
4739 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4740
4741 // Create a window with its bounds determined in the logical display.
4742 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4743 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4744 sp<FakeWindowHandle> window =
4745 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4746 window->setFrame(frameInDisplay, displayTransform);
4747 addWindow(window);
4748
4749 // The following points in logical display space should be inside the window.
4750 static const std::array<vec2, 4> insidePoints{
4751 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4752 for (const auto pointInsideWindow : insidePoints) {
4753 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4754 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004755 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4756 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4757 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004758 window->consumeMotionDown();
4759
Prabir Pradhan678438e2023-04-13 19:32:51 +00004760 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4761 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4762 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004763 window->consumeMotionUp();
4764 }
4765
4766 // The following points in logical display space should be outside the window.
4767 static const std::array<vec2, 5> outsidePoints{
4768 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4769 for (const auto pointOutsideWindow : outsidePoints) {
4770 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4771 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4773 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4774 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004775
Prabir Pradhan678438e2023-04-13 19:32:51 +00004776 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4777 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4778 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004779 }
4780 window->assertNoEvents();
4781}
4782
4783// Run the precision tests for all rotations.
4784INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4785 InputDispatcherDisplayOrientationFixture,
4786 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4787 ui::ROTATION_270),
4788 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4789 return ftl::enum_string(testParamInfo.param);
4790 });
4791
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004792using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4793 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004794
4795class TransferTouchFixture : public InputDispatcherTest,
4796 public ::testing::WithParamInterface<TransferFunction> {};
4797
4798TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004800
4801 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004802 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004803 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4804 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004805 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004806 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004807 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4808 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004809 sp<FakeWindowHandle> wallpaper =
4810 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4811 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004812 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004813 mDispatcher->onWindowInfosChanged(
4814 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004815
4816 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004817 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4818 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004819
Svet Ganov5d3bc372020-01-26 23:11:07 -08004820 // Only the first window should get the down event
4821 firstWindow->consumeMotionDown();
4822 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004823 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004824
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004825 // Transfer touch to the second window
4826 TransferFunction f = GetParam();
4827 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4828 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004829 // The first window gets cancel and the second gets down
4830 firstWindow->consumeMotionCancel();
4831 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004832 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004833
4834 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004835 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4836 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004837 // The first window gets no events and the second gets up
4838 firstWindow->assertNoEvents();
4839 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004840 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004841}
4842
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004843/**
4844 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4845 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4846 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4847 * natural to the user.
4848 * In this test, we are sending a pointer to both spy window and first window. We then try to
4849 * transfer touch to the second window. The dispatcher should identify the first window as the
4850 * one that should lose the gesture, and therefore the action should be to move the gesture from
4851 * the first window to the second.
4852 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4853 * the other API, as well.
4854 */
4855TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4857
4858 // Create a couple of windows + a spy window
4859 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004860 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004861 spyWindow->setTrustedOverlay(true);
4862 spyWindow->setSpy(true);
4863 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004864 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004865 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004866 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004867
4868 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004869 mDispatcher->onWindowInfosChanged(
4870 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004871
4872 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004873 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4874 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004875 // Only the first window and spy should get the down event
4876 spyWindow->consumeMotionDown();
4877 firstWindow->consumeMotionDown();
4878
4879 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4880 // if f === 'transferTouch'.
4881 TransferFunction f = GetParam();
4882 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4883 ASSERT_TRUE(success);
4884 // The first window gets cancel and the second gets down
4885 firstWindow->consumeMotionCancel();
4886 secondWindow->consumeMotionDown();
4887
4888 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004889 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4890 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004891 // The first window gets no events and the second+spy get up
4892 firstWindow->assertNoEvents();
4893 spyWindow->consumeMotionUp();
4894 secondWindow->consumeMotionUp();
4895}
4896
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004897TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004899
4900 PointF touchPoint = {10, 10};
4901
4902 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004903 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004904 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4905 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004906 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004907 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004908 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4909 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004910 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004911
4912 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004913 mDispatcher->onWindowInfosChanged(
4914 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004915
4916 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004917 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4918 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4919 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004920 // Only the first window should get the down event
4921 firstWindow->consumeMotionDown();
4922 secondWindow->assertNoEvents();
4923
4924 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004925 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4926 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004927 // Only the first window should get the pointer down event
4928 firstWindow->consumeMotionPointerDown(1);
4929 secondWindow->assertNoEvents();
4930
4931 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004932 TransferFunction f = GetParam();
4933 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4934 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004935 // The first window gets cancel and the second gets down and pointer down
4936 firstWindow->consumeMotionCancel();
4937 secondWindow->consumeMotionDown();
4938 secondWindow->consumeMotionPointerDown(1);
4939
4940 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004941 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4942 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004943 // The first window gets nothing and the second gets pointer up
4944 firstWindow->assertNoEvents();
4945 secondWindow->consumeMotionPointerUp(1);
4946
4947 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004948 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4949 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004950 // The first window gets nothing and the second gets up
4951 firstWindow->assertNoEvents();
4952 secondWindow->consumeMotionUp();
4953}
4954
Arthur Hungc539dbb2022-12-08 07:45:36 +00004955TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4956 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4957
4958 // Create a couple of windows
4959 sp<FakeWindowHandle> firstWindow =
4960 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4961 ADISPLAY_ID_DEFAULT);
4962 firstWindow->setDupTouchToWallpaper(true);
4963 sp<FakeWindowHandle> secondWindow =
4964 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4965 ADISPLAY_ID_DEFAULT);
4966 secondWindow->setDupTouchToWallpaper(true);
4967
4968 sp<FakeWindowHandle> wallpaper1 =
4969 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4970 wallpaper1->setIsWallpaper(true);
4971
4972 sp<FakeWindowHandle> wallpaper2 =
4973 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4974 wallpaper2->setIsWallpaper(true);
4975 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004976 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4977 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4978 {},
4979 0,
4980 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004981
4982 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004983 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4984 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004985
4986 // Only the first window should get the down event
4987 firstWindow->consumeMotionDown();
4988 secondWindow->assertNoEvents();
4989 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4990 wallpaper2->assertNoEvents();
4991
4992 // Transfer touch focus to the second window
4993 TransferFunction f = GetParam();
4994 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4995 ASSERT_TRUE(success);
4996
4997 // The first window gets cancel and the second gets down
4998 firstWindow->consumeMotionCancel();
4999 secondWindow->consumeMotionDown();
5000 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5001 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5002
5003 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005004 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5005 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005006 // The first window gets no events and the second gets up
5007 firstWindow->assertNoEvents();
5008 secondWindow->consumeMotionUp();
5009 wallpaper1->assertNoEvents();
5010 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5011}
5012
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005013// For the cases of single pointer touch and two pointers non-split touch, the api's
5014// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5015// for the case where there are multiple pointers split across several windows.
5016INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5017 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005018 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5019 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005020 return dispatcher->transferTouch(destChannelToken,
5021 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005022 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005023 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5024 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005025 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005026 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005027 }));
5028
Svet Ganov5d3bc372020-01-26 23:11:07 -08005029TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005031
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005032 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005033 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5034 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005035 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005036
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005037 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005038 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5039 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005040 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005041
5042 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005043 mDispatcher->onWindowInfosChanged(
5044 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005045
5046 PointF pointInFirst = {300, 200};
5047 PointF pointInSecond = {300, 600};
5048
5049 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005050 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5051 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5052 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005053 // Only the first window should get the down event
5054 firstWindow->consumeMotionDown();
5055 secondWindow->assertNoEvents();
5056
5057 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005058 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5059 ADISPLAY_ID_DEFAULT,
5060 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005061 // The first window gets a move and the second a down
5062 firstWindow->consumeMotionMove();
5063 secondWindow->consumeMotionDown();
5064
5065 // Transfer touch focus to the second window
5066 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5067 // The first window gets cancel and the new gets pointer down (it already saw down)
5068 firstWindow->consumeMotionCancel();
5069 secondWindow->consumeMotionPointerDown(1);
5070
5071 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005072 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5073 ADISPLAY_ID_DEFAULT,
5074 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005075 // The first window gets nothing and the second gets pointer up
5076 firstWindow->assertNoEvents();
5077 secondWindow->consumeMotionPointerUp(1);
5078
5079 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005080 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5081 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005082 // The first window gets nothing and the second gets up
5083 firstWindow->assertNoEvents();
5084 secondWindow->consumeMotionUp();
5085}
5086
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005087// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5088// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5089// touch is not supported, so the touch should continue on those windows and the transferred-to
5090// window should get nothing.
5091TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5093
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005094 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005095 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5096 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005097 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005098
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005099 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005100 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5101 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005102 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005103
5104 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005105 mDispatcher->onWindowInfosChanged(
5106 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005107
5108 PointF pointInFirst = {300, 200};
5109 PointF pointInSecond = {300, 600};
5110
5111 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005112 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5114 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005115 // Only the first window should get the down event
5116 firstWindow->consumeMotionDown();
5117 secondWindow->assertNoEvents();
5118
5119 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005120 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5121 ADISPLAY_ID_DEFAULT,
5122 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005123 // The first window gets a move and the second a down
5124 firstWindow->consumeMotionMove();
5125 secondWindow->consumeMotionDown();
5126
5127 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005128 const bool transferred =
5129 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005130 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5131 ASSERT_FALSE(transferred);
5132 firstWindow->assertNoEvents();
5133 secondWindow->assertNoEvents();
5134
5135 // The rest of the dispatch should proceed as normal
5136 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005137 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5138 ADISPLAY_ID_DEFAULT,
5139 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005140 // The first window gets MOVE and the second gets pointer up
5141 firstWindow->consumeMotionMove();
5142 secondWindow->consumeMotionUp();
5143
5144 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5146 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005147 // The first window gets nothing and the second gets up
5148 firstWindow->consumeMotionUp();
5149 secondWindow->assertNoEvents();
5150}
5151
Arthur Hungabbb9d82021-09-01 14:52:30 +00005152// This case will create two windows and one mirrored window on the default display and mirror
5153// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5154// the windows info of second display before default display.
5155TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5157 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005158 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005159 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005160 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005161 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005162 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005163
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005164 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005165 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005166
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005167 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005168 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005169
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005170 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005171 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005172
5173 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005174 mDispatcher->onWindowInfosChanged(
5175 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5176 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5177 *secondWindowInPrimary->getInfo()},
5178 {},
5179 0,
5180 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005181
5182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005184 {50, 50}))
5185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5186
5187 // Window should receive motion event.
5188 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5189
5190 // Transfer touch focus
5191 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5192 secondWindowInPrimary->getToken()));
5193 // The first window gets cancel.
5194 firstWindowInPrimary->consumeMotionCancel();
5195 secondWindowInPrimary->consumeMotionDown();
5196
5197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005198 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005199 ADISPLAY_ID_DEFAULT, {150, 50}))
5200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5201 firstWindowInPrimary->assertNoEvents();
5202 secondWindowInPrimary->consumeMotionMove();
5203
5204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005205 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005206 {150, 50}))
5207 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5208 firstWindowInPrimary->assertNoEvents();
5209 secondWindowInPrimary->consumeMotionUp();
5210}
5211
5212// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5213// 'transferTouch' api.
5214TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5215 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5216 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005217 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005218 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005219 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005220 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005221 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005222
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005223 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005224 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005225
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005226 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005227 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005228
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005229 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005230 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005231
5232 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005233 mDispatcher->onWindowInfosChanged(
5234 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5235 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5236 *secondWindowInPrimary->getInfo()},
5237 {},
5238 0,
5239 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005240
5241 // Touch on second display.
5242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5244 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5246
5247 // Window should receive motion event.
5248 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5249
5250 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005251 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005252
5253 // The first window gets cancel.
5254 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5255 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5256
5257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005258 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005259 SECOND_DISPLAY_ID, {150, 50}))
5260 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5261 firstWindowInPrimary->assertNoEvents();
5262 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5263
5264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005265 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005266 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5267 firstWindowInPrimary->assertNoEvents();
5268 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5269}
5270
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005271TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005273 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5274 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005275
Vishnu Nair47074b82020-08-14 11:54:47 -07005276 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005277 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005278 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005279
5280 window->consumeFocusEvent(true);
5281
Prabir Pradhan678438e2023-04-13 19:32:51 +00005282 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005283
5284 // Window should receive key down event.
5285 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005286
5287 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005288 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005289 mFakePolicy->assertUserActivityPoked();
5290}
5291
5292TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5293 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5294 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5295 "Fake Window", ADISPLAY_ID_DEFAULT);
5296
5297 window->setDisableUserActivity(true);
5298 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005299 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005300 setFocusedWindow(window);
5301
5302 window->consumeFocusEvent(true);
5303
5304 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5305
5306 // Window should receive key down event.
5307 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5308
5309 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005310 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005311 mFakePolicy->assertUserActivityNotPoked();
5312}
5313
5314TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5316 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5317 "Fake Window", ADISPLAY_ID_DEFAULT);
5318
5319 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005320 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005321 setFocusedWindow(window);
5322
5323 window->consumeFocusEvent(true);
5324
5325 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5326 mDispatcher->waitForIdle();
5327
5328 // System key is not passed down
5329 window->assertNoEvents();
5330
5331 // Should have poked user activity
5332 mFakePolicy->assertUserActivityPoked();
5333}
5334
5335TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5336 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5337 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5338 "Fake Window", ADISPLAY_ID_DEFAULT);
5339
5340 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005341 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005342 setFocusedWindow(window);
5343
5344 window->consumeFocusEvent(true);
5345
5346 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5347 mDispatcher->waitForIdle();
5348
5349 // System key is not passed down
5350 window->assertNoEvents();
5351
5352 // Should have poked user activity
5353 mFakePolicy->assertUserActivityPoked();
5354}
5355
5356TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5357 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5358 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5359 "Fake Window", ADISPLAY_ID_DEFAULT);
5360
5361 window->setDisableUserActivity(true);
5362 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005364 setFocusedWindow(window);
5365
5366 window->consumeFocusEvent(true);
5367
5368 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5369 mDispatcher->waitForIdle();
5370
5371 // System key is not passed down
5372 window->assertNoEvents();
5373
5374 // Should have poked user activity
5375 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005376}
5377
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005378TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5380 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5381 "Fake Window", ADISPLAY_ID_DEFAULT);
5382
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005383 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005384
5385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005386 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005387 ADISPLAY_ID_DEFAULT, {100, 100}))
5388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5389
5390 window->consumeMotionEvent(
5391 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5392
5393 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005394 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005395 mFakePolicy->assertUserActivityPoked();
5396}
5397
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005398TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
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
Prabir Pradhan678438e2023-04-13 19:32:51 +00005405 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005406 mDispatcher->waitForIdle();
5407
5408 window->assertNoEvents();
5409}
5410
5411// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5412TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005414 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5415 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005416
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005417 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005418
5419 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005420 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005421 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5423 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005424
5425 // Window should receive only the motion event
5426 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5427 window->assertNoEvents(); // Key event or focus event will not be received
5428}
5429
arthurhungea3f4fc2020-12-21 23:18:53 +08005430TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5432
arthurhungea3f4fc2020-12-21 23:18:53 +08005433 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005434 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5435 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005436 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005437
arthurhungea3f4fc2020-12-21 23:18:53 +08005438 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005439 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5440 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005441 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005442
5443 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005444 mDispatcher->onWindowInfosChanged(
5445 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005446
5447 PointF pointInFirst = {300, 200};
5448 PointF pointInSecond = {300, 600};
5449
5450 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005451 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5452 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5453 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005454 // Only the first window should get the down event
5455 firstWindow->consumeMotionDown();
5456 secondWindow->assertNoEvents();
5457
5458 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005459 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5460 ADISPLAY_ID_DEFAULT,
5461 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005462 // The first window gets a move and the second a down
5463 firstWindow->consumeMotionMove();
5464 secondWindow->consumeMotionDown();
5465
5466 // Send pointer cancel to the second window
5467 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005468 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005469 {pointInFirst, pointInSecond});
5470 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005471 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005472 // The first window gets move and the second gets cancel.
5473 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5474 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5475
5476 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005477 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5478 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005479 // The first window gets up and the second gets nothing.
5480 firstWindow->consumeMotionUp();
5481 secondWindow->assertNoEvents();
5482}
5483
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005484TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5486
5487 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005488 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005490 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5491 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5492 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5493
Harry Cutts33476232023-01-30 19:57:29 +00005494 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005495 window->assertNoEvents();
5496 mDispatcher->waitForIdle();
5497}
5498
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005499using InputDispatcherMonitorTest = InputDispatcherTest;
5500
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005501/**
5502 * Two entities that receive touch: A window, and a global monitor.
5503 * The touch goes to the window, and then the window disappears.
5504 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5505 * for the monitor, as well.
5506 * 1. foregroundWindow
5507 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5508 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005509TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005510 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5511 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005512 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005513
Prabir Pradhanfb549072023-10-05 19:17:36 +00005514 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005515
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005516 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005518 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005519 {100, 200}))
5520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5521
5522 // Both the foreground window and the global monitor should receive the touch down
5523 window->consumeMotionDown();
5524 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5525
5526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005527 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005528 ADISPLAY_ID_DEFAULT, {110, 200}))
5529 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5530
5531 window->consumeMotionMove();
5532 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5533
5534 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005535 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005536 window->consumeMotionCancel();
5537 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5538
5539 // If more events come in, there will be no more foreground window to send them to. This will
5540 // cause a cancel for the monitor, as well.
5541 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005542 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005543 ADISPLAY_ID_DEFAULT, {120, 200}))
5544 << "Injection should fail because the window was removed";
5545 window->assertNoEvents();
5546 // Global monitor now gets the cancel
5547 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5548}
5549
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005550TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005552 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5553 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005555
Prabir Pradhanfb549072023-10-05 19:17:36 +00005556 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005557
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005559 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005561 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005562 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005563}
5564
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005565TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005566 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005567
Chris Yea209fde2020-07-22 13:54:51 -07005568 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005569 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5570 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005571 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005572
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005574 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005576 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005577 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005578
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005579 // Pilfer pointers from the monitor.
5580 // This should not do anything and the window should continue to receive events.
5581 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005582
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005584 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005585 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005586 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005587
5588 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5589 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005590}
5591
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005592TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005594 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5595 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005596 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005597 window->setWindowOffset(20, 40);
5598 window->setWindowTransform(0, 1, -1, 0);
5599
Prabir Pradhanfb549072023-10-05 19:17:36 +00005600 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005601
5602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005603 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5605 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5606 MotionEvent* event = monitor.consumeMotion();
5607 // Even though window has transform, gesture monitor must not.
5608 ASSERT_EQ(ui::Transform(), event->getTransform());
5609}
5610
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005611TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005612 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005613 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005614
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005615 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005616 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005617 << "Injection should fail if there is a monitor, but no touchable window";
5618 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005619}
5620
chaviw81e2bb92019-12-18 15:03:51 -08005621TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005623 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5624 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005625
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005626 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005627
5628 NotifyMotionArgs motionArgs =
5629 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5630 ADISPLAY_ID_DEFAULT);
5631
Prabir Pradhan678438e2023-04-13 19:32:51 +00005632 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005633 // Window should receive motion down event.
5634 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5635
5636 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005637 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005638 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5639 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5640 motionArgs.pointerCoords[0].getX() - 10);
5641
Prabir Pradhan678438e2023-04-13 19:32:51 +00005642 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005643 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005644 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005645}
5646
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005647/**
5648 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5649 * the device default right away. In the test scenario, we check both the default value,
5650 * and the action of enabling / disabling.
5651 */
5652TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005654 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5655 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005656 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005657
5658 // Set focused application.
5659 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005660 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005661
5662 SCOPED_TRACE("Check default value of touch mode");
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=*/true);
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=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005671
5672 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005673 mDispatcher->setInTouchMode(false, 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(false);
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=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005680
5681 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005682 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005683 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005684 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005685
5686 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005687 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005688 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005689 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005690 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005691 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005692 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005693 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005694
5695 window->assertNoEvents();
5696}
5697
Gang Wange9087892020-01-07 12:17:14 -05005698TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005700 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5701 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005702
5703 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005704 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005705
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005706 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005707 setFocusedWindow(window);
5708
Harry Cutts33476232023-01-30 19:57:29 +00005709 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005710
Prabir Pradhan678438e2023-04-13 19:32:51 +00005711 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5712 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005713
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005714 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005715 ASSERT_NE(event, nullptr);
5716
5717 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5718 ASSERT_NE(verified, nullptr);
5719 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5720
5721 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5722 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5723 ASSERT_EQ(keyArgs.source, verified->source);
5724 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5725
5726 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5727
5728 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005729 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005730 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005731 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5732 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5733 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5734 ASSERT_EQ(0, verifiedKey.repeatCount);
5735}
5736
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005737TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005739 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5740 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005741
5742 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5743
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005744 ui::Transform transform;
5745 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5746
5747 gui::DisplayInfo displayInfo;
5748 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5749 displayInfo.transform = transform;
5750
Patrick Williamsd828f302023-04-28 17:52:08 -05005751 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005752
Prabir Pradhan678438e2023-04-13 19:32:51 +00005753 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005754 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5755 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005756 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005757
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005758 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005759 ASSERT_NE(event, nullptr);
5760
5761 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5762 ASSERT_NE(verified, nullptr);
5763 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5764
5765 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5766 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5767 EXPECT_EQ(motionArgs.source, verified->source);
5768 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5769
5770 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5771
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005772 const vec2 rawXY =
5773 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5774 motionArgs.pointerCoords[0].getXYValue());
5775 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5776 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005777 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005778 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005779 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005780 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5781 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5782}
5783
chaviw09c8d2d2020-08-24 15:48:26 -07005784/**
5785 * Ensure that separate calls to sign the same data are generating the same key.
5786 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5787 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5788 * tests.
5789 */
5790TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5791 KeyEvent event = getTestKeyEvent();
5792 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5793
5794 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5795 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5796 ASSERT_EQ(hmac1, hmac2);
5797}
5798
5799/**
5800 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5801 */
5802TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5803 KeyEvent event = getTestKeyEvent();
5804 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5805 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5806
5807 verifiedEvent.deviceId += 1;
5808 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5809
5810 verifiedEvent.source += 1;
5811 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5812
5813 verifiedEvent.eventTimeNanos += 1;
5814 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5815
5816 verifiedEvent.displayId += 1;
5817 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5818
5819 verifiedEvent.action += 1;
5820 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5821
5822 verifiedEvent.downTimeNanos += 1;
5823 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5824
5825 verifiedEvent.flags += 1;
5826 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5827
5828 verifiedEvent.keyCode += 1;
5829 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5830
5831 verifiedEvent.scanCode += 1;
5832 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5833
5834 verifiedEvent.metaState += 1;
5835 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5836
5837 verifiedEvent.repeatCount += 1;
5838 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5839}
5840
Vishnu Nair958da932020-08-21 17:12:37 -07005841TEST_F(InputDispatcherTest, SetFocusedWindow) {
5842 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5843 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005844 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005845 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005846 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5848
5849 // Top window is also focusable but is not granted focus.
5850 windowTop->setFocusable(true);
5851 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005852 mDispatcher->onWindowInfosChanged(
5853 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005854 setFocusedWindow(windowSecond);
5855
5856 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005858 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005859
5860 // Focused window should receive event.
5861 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5862 windowTop->assertNoEvents();
5863}
5864
5865TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5867 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005868 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005869 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5870
5871 window->setFocusable(true);
5872 // Release channel for window is no longer valid.
5873 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005874 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005875 setFocusedWindow(window);
5876
5877 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005878 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005879
5880 // window channel is invalid, so it should not receive any input event.
5881 window->assertNoEvents();
5882}
5883
5884TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5885 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5886 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005887 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005888 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005889 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5890
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005891 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005892 setFocusedWindow(window);
5893
5894 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005895 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005896
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005897 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005898 window->assertNoEvents();
5899}
5900
5901TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5903 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005904 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005905 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005906 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005907 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5908
5909 windowTop->setFocusable(true);
5910 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005911 mDispatcher->onWindowInfosChanged(
5912 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005913 setFocusedWindow(windowTop);
5914 windowTop->consumeFocusEvent(true);
5915
Chavi Weingarten847e8512023-03-29 00:26:09 +00005916 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005917 mDispatcher->onWindowInfosChanged(
5918 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005919 windowSecond->consumeFocusEvent(true);
5920 windowTop->consumeFocusEvent(false);
5921
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005923 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005924
5925 // Focused window should receive event.
5926 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5927}
5928
Chavi Weingarten847e8512023-03-29 00:26:09 +00005929TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5931 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005932 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005933 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005934 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005935 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5936
5937 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005938 windowSecond->setFocusable(false);
5939 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005940 mDispatcher->onWindowInfosChanged(
5941 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005942 setFocusedWindow(windowTop);
5943 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005944
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005946 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005947
5948 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005949 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005950 windowSecond->assertNoEvents();
5951}
5952
5953TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5955 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005956 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005957 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005958 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5959 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005960 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5961
5962 window->setFocusable(true);
5963 previousFocusedWindow->setFocusable(true);
5964 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005965 mDispatcher->onWindowInfosChanged(
5966 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005967 setFocusedWindow(previousFocusedWindow);
5968 previousFocusedWindow->consumeFocusEvent(true);
5969
5970 // Requesting focus on invisible window takes focus from currently focused window.
5971 setFocusedWindow(window);
5972 previousFocusedWindow->consumeFocusEvent(false);
5973
5974 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005976 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5977 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005978
5979 // Window does not get focus event or key down.
5980 window->assertNoEvents();
5981
5982 // Window becomes visible.
5983 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005984 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005985
5986 // Window receives focus event.
5987 window->consumeFocusEvent(true);
5988 // Focused window receives key down.
5989 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5990}
5991
Vishnu Nair599f1412021-06-21 10:39:58 -07005992TEST_F(InputDispatcherTest, DisplayRemoved) {
5993 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5994 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005995 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005996 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5997
5998 // window is granted focus.
5999 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006000 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006001 setFocusedWindow(window);
6002 window->consumeFocusEvent(true);
6003
6004 // When a display is removed window loses focus.
6005 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6006 window->consumeFocusEvent(false);
6007}
6008
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006009/**
6010 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6011 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6012 * of the 'slipperyEnterWindow'.
6013 *
6014 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6015 * a way so that the touched location is no longer covered by the top window.
6016 *
6017 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6018 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6019 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6020 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6021 * with ACTION_DOWN).
6022 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6023 * window moved itself away from the touched location and had Flag::SLIPPERY.
6024 *
6025 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6026 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6027 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6028 *
6029 * In this test, we ensure that the event received by the bottom window has
6030 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6031 */
6032TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006033 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006034 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006035
6036 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6037 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6038
6039 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006040 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006041 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006042 // Make sure this one overlaps the bottom window
6043 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6044 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6045 // one. Windows with the same owner are not considered to be occluding each other.
6046 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6047
6048 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006049 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006050 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6051
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006052 mDispatcher->onWindowInfosChanged(
6053 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006054
6055 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006056 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6057 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6058 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006059 slipperyExitWindow->consumeMotionDown();
6060 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006061 mDispatcher->onWindowInfosChanged(
6062 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006063
Prabir Pradhan678438e2023-04-13 19:32:51 +00006064 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6065 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6066 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006067
6068 slipperyExitWindow->consumeMotionCancel();
6069
6070 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6071 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6072}
6073
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006074/**
6075 * Two windows, one on the left and another on the right. The left window is slippery. The right
6076 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6077 * touch moves from the left window into the right window, the gesture should continue to go to the
6078 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6079 * reproduces a crash.
6080 */
6081TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6083
6084 sp<FakeWindowHandle> leftSlipperyWindow =
6085 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6086 leftSlipperyWindow->setSlippery(true);
6087 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6088
6089 sp<FakeWindowHandle> rightDropTouchesWindow =
6090 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6091 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6092 rightDropTouchesWindow->setDropInput(true);
6093
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006094 mDispatcher->onWindowInfosChanged(
6095 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006096
6097 // Start touch in the left window
6098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6099 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6100 .build());
6101 leftSlipperyWindow->consumeMotionDown();
6102
6103 // And move it into the right window
6104 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6105 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6106 .build());
6107
6108 // Since the right window isn't eligible to receive input, touch does not slip.
6109 // The left window continues to receive the gesture.
6110 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6111 rightDropTouchesWindow->assertNoEvents();
6112}
6113
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006114/**
6115 * A single window is on screen first. Touch is injected into that window. Next, a second window
6116 * appears. Since the first window is slippery, touch will move from the first window to the second.
6117 */
6118TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6120 sp<FakeWindowHandle> originalWindow =
6121 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6122 originalWindow->setFrame(Rect(0, 0, 200, 200));
6123 originalWindow->setSlippery(true);
6124
6125 sp<FakeWindowHandle> appearingWindow =
6126 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6127 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6128
6129 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6130
6131 // Touch down on the original window
6132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6133 injectMotionEvent(*mDispatcher,
6134 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6135 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6136 .build()));
6137 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6138
6139 // Now, a new window appears. This could be, for example, a notification shade that appears
6140 // after user starts to drag down on the launcher window.
6141 mDispatcher->onWindowInfosChanged(
6142 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6144 injectMotionEvent(*mDispatcher,
6145 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6146 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6147 .build()));
6148 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6149 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6151 injectMotionEvent(*mDispatcher,
6152 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6153 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6154 .build()));
6155 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6156
6157 originalWindow->assertNoEvents();
6158 appearingWindow->assertNoEvents();
6159}
6160
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006161TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006162 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006163 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6164
6165 sp<FakeWindowHandle> leftWindow =
6166 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6167 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006168 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006169
6170 sp<FakeWindowHandle> rightSpy =
6171 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6172 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006173 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006174 rightSpy->setSpy(true);
6175 rightSpy->setTrustedOverlay(true);
6176
6177 sp<FakeWindowHandle> rightWindow =
6178 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6179 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006180 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006181
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006182 mDispatcher->onWindowInfosChanged(
6183 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006184
6185 // Touch in the left window
6186 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6187 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6188 .build());
6189 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6190 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006191 ASSERT_NO_FATAL_FAILURE(
6192 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006193
6194 // Touch another finger over the right windows
6195 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6196 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6197 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6198 .build());
6199 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6200 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6201 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6202 mDispatcher->waitForIdle();
6203 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006204 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6205 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006206
6207 // Release finger over left window. The UP actions are not treated as device interaction.
6208 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6209 // is part of the UP action, we do not treat this as device interaction.
6210 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6211 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6212 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6213 .build());
6214 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6215 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6216 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6217 mDispatcher->waitForIdle();
6218 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6219
6220 // Move remaining finger
6221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6222 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6223 .build());
6224 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6225 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6226 mDispatcher->waitForIdle();
6227 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006228 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006229
6230 // Release all fingers
6231 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6232 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6233 .build());
6234 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6235 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6236 mDispatcher->waitForIdle();
6237 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6238}
6239
6240TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6242
6243 sp<FakeWindowHandle> window =
6244 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6245 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006246 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006247
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006248 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006249 setFocusedWindow(window);
6250 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6251
6252 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6253 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6254 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006255 ASSERT_NO_FATAL_FAILURE(
6256 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006257
6258 // The UP actions are not treated as device interaction.
6259 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6260 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6261 mDispatcher->waitForIdle();
6262 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6263}
6264
Garfield Tan1c7bc862020-01-28 13:24:04 -08006265class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6266protected:
6267 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6268 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6269
Chris Yea209fde2020-07-22 13:54:51 -07006270 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006271 sp<FakeWindowHandle> mWindow;
6272
6273 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006274 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006275 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006276 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006277 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006278 ASSERT_EQ(OK, mDispatcher->start());
6279
6280 setUpWindow();
6281 }
6282
6283 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006284 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006285 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006286
Vishnu Nair47074b82020-08-14 11:54:47 -07006287 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006288 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006289 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006290 mWindow->consumeFocusEvent(true);
6291 }
6292
Chris Ye2ad95392020-09-01 13:44:44 -07006293 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006294 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006295 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006296 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006297 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006298
6299 // Window should receive key down event.
6300 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6301 }
6302
6303 void expectKeyRepeatOnce(int32_t repeatCount) {
6304 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006305 mWindow->consumeKeyEvent(
6306 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006307 }
6308
Chris Ye2ad95392020-09-01 13:44:44 -07006309 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006310 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006311 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006312 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006313 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006314
6315 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006316 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006317 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006318 }
6319};
6320
6321TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006322 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006323 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6324 expectKeyRepeatOnce(repeatCount);
6325 }
6326}
6327
6328TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006329 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006330 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6331 expectKeyRepeatOnce(repeatCount);
6332 }
Harry Cutts33476232023-01-30 19:57:29 +00006333 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006334 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006335 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6336 expectKeyRepeatOnce(repeatCount);
6337 }
6338}
6339
6340TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006341 sendAndConsumeKeyDown(/*deviceId=*/1);
6342 expectKeyRepeatOnce(/*repeatCount=*/1);
6343 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006344 mWindow->assertNoEvents();
6345}
6346
6347TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006348 sendAndConsumeKeyDown(/*deviceId=*/1);
6349 expectKeyRepeatOnce(/*repeatCount=*/1);
6350 sendAndConsumeKeyDown(/*deviceId=*/2);
6351 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006352 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006353 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006354 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006355 expectKeyRepeatOnce(/*repeatCount=*/2);
6356 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006357 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006358 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006359 mWindow->assertNoEvents();
6360}
6361
6362TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006363 sendAndConsumeKeyDown(/*deviceId=*/1);
6364 expectKeyRepeatOnce(/*repeatCount=*/1);
6365 sendAndConsumeKeyDown(/*deviceId=*/2);
6366 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006367 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006368 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006369 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006370 mWindow->assertNoEvents();
6371}
6372
liushenxiang42232912021-05-21 20:24:09 +08006373TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6374 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006375 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006376 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006377 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6378 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6379 mWindow->assertNoEvents();
6380}
6381
Garfield Tan1c7bc862020-01-28 13:24:04 -08006382TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006383 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006384 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006385 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006386 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006387 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6388 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6389 IdGenerator::getSource(repeatEvent->getId()));
6390 }
6391}
6392
6393TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006394 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006395 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006396
6397 std::unordered_set<int32_t> idSet;
6398 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006399 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006400 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6401 int32_t id = repeatEvent->getId();
6402 EXPECT_EQ(idSet.end(), idSet.find(id));
6403 idSet.insert(id);
6404 }
6405}
6406
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006407/* Test InputDispatcher for MultiDisplay */
6408class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6409public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006410 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006411 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006412
Chris Yea209fde2020-07-22 13:54:51 -07006413 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006414 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006415 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006416
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006417 // Set focus window for primary display, but focused display would be second one.
6418 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006419 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006420 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6421
Vishnu Nair958da932020-08-21 17:12:37 -07006422 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006423 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006424
Chris Yea209fde2020-07-22 13:54:51 -07006425 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006426 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006427 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006428 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006429 // Set focus display to second one.
6430 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6431 // Set focus window for second display.
6432 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006433 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006434 mDispatcher->onWindowInfosChanged(
6435 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006436 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006437 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006438 }
6439
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006440 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006441 InputDispatcherTest::TearDown();
6442
Chris Yea209fde2020-07-22 13:54:51 -07006443 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006444 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006445 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006446 windowInSecondary.clear();
6447 }
6448
6449protected:
Chris Yea209fde2020-07-22 13:54:51 -07006450 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006451 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006452 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006453 sp<FakeWindowHandle> windowInSecondary;
6454};
6455
6456TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6457 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006459 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006460 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006461 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006462 windowInSecondary->assertNoEvents();
6463
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006464 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006466 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006468 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006469 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006470}
6471
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006472TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006473 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006475 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006476 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006477 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006478 windowInSecondary->assertNoEvents();
6479
6480 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006482 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006483 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006484 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006485
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006486 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006487 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006488
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006489 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006490 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006491 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006492
6493 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006494 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006495 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006496 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006497 windowInSecondary->assertNoEvents();
6498}
6499
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006500// Test per-display input monitors for motion event.
6501TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006502 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006503 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006504 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006505 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006506
6507 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006509 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006511 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006512 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006513 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006514 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006515
6516 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006518 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006519 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006520 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006521 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006522 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006523 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006524
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006525 // Lift up the touch from the second display
6526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006527 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006528 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6529 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6530 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6531
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006532 // Test inject a non-pointer motion event.
6533 // If specific a display, it will dispatch to the focused window of particular display,
6534 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006536 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006537 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006538 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006539 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006540 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006541 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006542}
6543
6544// Test per-display input monitors for key event.
6545TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006546 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006547 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006548 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006549 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006550 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006551
6552 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006554 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006555 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006556 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006557 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006558 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006559}
6560
Vishnu Nair958da932020-08-21 17:12:37 -07006561TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6562 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006563 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006564 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006565 mDispatcher->onWindowInfosChanged(
6566 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6567 *windowInSecondary->getInfo()},
6568 {},
6569 0,
6570 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006571 setFocusedWindow(secondWindowInPrimary);
6572 windowInPrimary->consumeFocusEvent(false);
6573 secondWindowInPrimary->consumeFocusEvent(true);
6574
6575 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6577 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006578 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006579 windowInPrimary->assertNoEvents();
6580 windowInSecondary->assertNoEvents();
6581 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6582}
6583
Arthur Hungdfd528e2021-12-08 13:23:04 +00006584TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6585 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006586 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006587 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00006588 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00006589
6590 // Test touch down on primary display.
6591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6594 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6595 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6596
6597 // Test touch down on second display.
6598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006599 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6601 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6602 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6603
6604 // Trigger cancel touch.
6605 mDispatcher->cancelCurrentTouch();
6606 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6607 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6608 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6609 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6610
6611 // Test inject a move motion event, no window/monitor should receive the event.
6612 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006613 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006614 ADISPLAY_ID_DEFAULT, {110, 200}))
6615 << "Inject motion event should return InputEventInjectionResult::FAILED";
6616 windowInPrimary->assertNoEvents();
6617 monitorInPrimary.assertNoEvents();
6618
6619 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006620 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006621 SECOND_DISPLAY_ID, {110, 200}))
6622 << "Inject motion event should return InputEventInjectionResult::FAILED";
6623 windowInSecondary->assertNoEvents();
6624 monitorInSecondary.assertNoEvents();
6625}
6626
Jackal Guof9696682018-10-05 12:23:23 +08006627class InputFilterTest : public InputDispatcherTest {
6628protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006629 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6630 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006631 NotifyMotionArgs motionArgs;
6632
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006633 motionArgs =
6634 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006635 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006636 motionArgs =
6637 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006638 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006639 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006640 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006641 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006642 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006643 } else {
6644 mFakePolicy->assertFilterInputEventWasNotCalled();
6645 }
6646 }
6647
6648 void testNotifyKey(bool expectToBeFiltered) {
6649 NotifyKeyArgs keyArgs;
6650
6651 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006652 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006653 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006654 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006655 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006656
6657 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006658 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006659 } else {
6660 mFakePolicy->assertFilterInputEventWasNotCalled();
6661 }
6662 }
6663};
6664
6665// Test InputFilter for MotionEvent
6666TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6667 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006668 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6669 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006670
6671 // Enable InputFilter
6672 mDispatcher->setInputFilterEnabled(true);
6673 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006674 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6675 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006676
6677 // Disable InputFilter
6678 mDispatcher->setInputFilterEnabled(false);
6679 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006680 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6681 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006682}
6683
6684// Test InputFilter for KeyEvent
6685TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6686 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006687 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006688
6689 // Enable InputFilter
6690 mDispatcher->setInputFilterEnabled(true);
6691 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006692 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006693
6694 // Disable InputFilter
6695 mDispatcher->setInputFilterEnabled(false);
6696 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006697 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006698}
6699
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006700// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6701// logical display coordinate space.
6702TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6703 ui::Transform firstDisplayTransform;
6704 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6705 ui::Transform secondDisplayTransform;
6706 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6707
6708 std::vector<gui::DisplayInfo> displayInfos(2);
6709 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6710 displayInfos[0].transform = firstDisplayTransform;
6711 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6712 displayInfos[1].transform = secondDisplayTransform;
6713
Patrick Williamsd828f302023-04-28 17:52:08 -05006714 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006715
6716 // Enable InputFilter
6717 mDispatcher->setInputFilterEnabled(true);
6718
6719 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006720 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6721 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006722}
6723
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006724class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6725protected:
6726 virtual void SetUp() override {
6727 InputDispatcherTest::SetUp();
6728
6729 /**
6730 * We don't need to enable input filter to test the injected event policy, but we enabled it
6731 * here to make the tests more realistic, since this policy only matters when inputfilter is
6732 * on.
6733 */
6734 mDispatcher->setInputFilterEnabled(true);
6735
6736 std::shared_ptr<InputApplicationHandle> application =
6737 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006738 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6739 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006740
6741 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6742 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006743 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006744 setFocusedWindow(mWindow);
6745 mWindow->consumeFocusEvent(true);
6746 }
6747
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006748 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6749 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006750 KeyEvent event;
6751
6752 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6753 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6754 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006755 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006756 const int32_t additionalPolicyFlags =
6757 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006759 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006760 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006761 policyFlags | additionalPolicyFlags));
6762
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006763 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006764 }
6765
6766 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6767 int32_t flags) {
6768 MotionEvent event;
6769 PointerProperties pointerProperties[1];
6770 PointerCoords pointerCoords[1];
6771 pointerProperties[0].clear();
6772 pointerProperties[0].id = 0;
6773 pointerCoords[0].clear();
6774 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6775 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6776
6777 ui::Transform identityTransform;
6778 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6779 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6780 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6781 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006784 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006785 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006786
6787 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006789 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006790 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006791 policyFlags | additionalPolicyFlags));
6792
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006793 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006794 }
6795
6796private:
6797 sp<FakeWindowHandle> mWindow;
6798};
6799
6800TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006801 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6802 // filter. Without it, the event will no different from a regularly injected event, and the
6803 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006804 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6805 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006806}
6807
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006808TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006809 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006810 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006811 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6812}
6813
6814TEST_F(InputFilterInjectionPolicyTest,
6815 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6816 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006817 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006818 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006819}
6820
6821TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006822 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6823 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006824}
6825
chaviwfd6d3512019-03-25 13:23:49 -07006826class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006827 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006828 InputDispatcherTest::SetUp();
6829
Chris Yea209fde2020-07-22 13:54:51 -07006830 std::shared_ptr<FakeApplicationHandle> application =
6831 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006832 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006833 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006834 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006835
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006836 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006837 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006838 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006839
6840 // Set focused application.
6841 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006842 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006843
6844 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006845 mDispatcher->onWindowInfosChanged(
6846 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006847 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006848 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006849 }
6850
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006851 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006852 InputDispatcherTest::TearDown();
6853
6854 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006855 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006856 }
6857
6858protected:
6859 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006860 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006861 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006862};
6863
6864// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6865// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6866// the onPointerDownOutsideFocus callback.
6867TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006870 {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 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006873
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006874 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006875 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6876}
6877
6878// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6879// DOWN on the window that doesn't have focus. Ensure no window received the
6880// onPointerDownOutsideFocus callback.
6881TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006883 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6884 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006885 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006886 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006887
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006888 ASSERT_TRUE(mDispatcher->waitForIdle());
6889 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006890}
6891
6892// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6893// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6894TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006896 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006897 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006898 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
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
6904// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6905// DOWN on the window that already has focus. Ensure no window received the
6906// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006907TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006909 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006910 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006911 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006912 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006913
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006914 ASSERT_TRUE(mDispatcher->waitForIdle());
6915 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006916}
6917
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006918// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6919// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6920TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6921 const MotionEvent event =
6922 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6923 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006924 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006925 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6926 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6929 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6930
6931 ASSERT_TRUE(mDispatcher->waitForIdle());
6932 mFakePolicy->assertOnPointerDownWasNotCalled();
6933 // Ensure that the unfocused window did not receive any FOCUS events.
6934 mUnfocusedWindow->assertNoEvents();
6935}
6936
chaviwaf87b3e2019-10-01 16:59:28 -07006937// These tests ensures we can send touch events to a single client when there are multiple input
6938// windows that point to the same client token.
6939class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6940 virtual void SetUp() override {
6941 InputDispatcherTest::SetUp();
6942
Chris Yea209fde2020-07-22 13:54:51 -07006943 std::shared_ptr<FakeApplicationHandle> application =
6944 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006945 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6946 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006947 mWindow1->setFrame(Rect(0, 0, 100, 100));
6948
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006949 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6950 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006951 mWindow2->setFrame(Rect(100, 100, 200, 200));
6952
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006953 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006954 }
6955
6956protected:
6957 sp<FakeWindowHandle> mWindow1;
6958 sp<FakeWindowHandle> mWindow2;
6959
6960 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006961 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006962 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6963 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006964 }
6965
6966 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6967 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006968 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006969 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006970
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006971 ASSERT_NE(nullptr, motionEvent)
6972 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006973
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006974 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006975 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006976
6977 for (size_t i = 0; i < points.size(); i++) {
6978 float expectedX = points[i].x;
6979 float expectedY = points[i].y;
6980
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006981 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006982 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006983 << ", got " << motionEvent->getX(i);
6984 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006985 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006986 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006987 }
6988 }
chaviw9eaa22c2020-07-01 16:21:27 -07006989
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006990 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006991 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006992 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6993 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006994
6995 // Always consume from window1 since it's the window that has the InputReceiver
6996 consumeMotionEvent(mWindow1, action, expectedPoints);
6997 }
chaviwaf87b3e2019-10-01 16:59:28 -07006998};
6999
7000TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7001 // Touch Window 1
7002 PointF touchedPoint = {10, 10};
7003 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007004 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007005
7006 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007007 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007008
7009 // Touch Window 2
7010 touchedPoint = {150, 150};
7011 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007012 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007013}
7014
chaviw9eaa22c2020-07-01 16:21:27 -07007015TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7016 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007017 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007018 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007019
7020 // Touch Window 1
7021 PointF touchedPoint = {10, 10};
7022 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007023 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007024 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007025 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007026
7027 // Touch Window 2
7028 touchedPoint = {150, 150};
7029 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007030 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7031 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007032
chaviw9eaa22c2020-07-01 16:21:27 -07007033 // Update the transform so rotation is set
7034 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007035 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007036 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7037 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007038}
7039
chaviw9eaa22c2020-07-01 16:21:27 -07007040TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007041 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007042 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007043
7044 // Touch Window 1
7045 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7046 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007047 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007048
7049 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007050 touchedPoints.push_back(PointF{150, 150});
7051 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007052 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007053
chaviw9eaa22c2020-07-01 16:21:27 -07007054 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007055 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007056 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007057
chaviw9eaa22c2020-07-01 16:21:27 -07007058 // Update the transform so rotation is set for Window 2
7059 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007060 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007061 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007062 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007063}
7064
chaviw9eaa22c2020-07-01 16:21:27 -07007065TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007066 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007067 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007068
7069 // Touch Window 1
7070 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7071 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007072 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007073
7074 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007075 touchedPoints.push_back(PointF{150, 150});
7076 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007077
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007078 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007079
7080 // Move both windows
7081 touchedPoints = {{20, 20}, {175, 175}};
7082 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7083 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7084
chaviw9eaa22c2020-07-01 16:21:27 -07007085 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007086
chaviw9eaa22c2020-07-01 16:21:27 -07007087 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007088 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007089 expectedPoints.pop_back();
7090
7091 // Touch Window 2
7092 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007093 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007094 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007095 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007096
7097 // Move both windows
7098 touchedPoints = {{20, 20}, {175, 175}};
7099 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7100 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7101
7102 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007103}
7104
7105TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7106 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007107 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007108
7109 // Touch Window 1
7110 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7111 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007112 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007113
7114 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007115 touchedPoints.push_back(PointF{150, 150});
7116 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007117
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007118 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007119
7120 // Move both windows
7121 touchedPoints = {{20, 20}, {175, 175}};
7122 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7123 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7124
chaviw9eaa22c2020-07-01 16:21:27 -07007125 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007126}
7127
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007128/**
7129 * When one of the windows is slippery, the touch should not slip into the other window with the
7130 * same input channel.
7131 */
7132TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7133 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007134 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007135
7136 // Touch down in window 1
7137 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7138 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7139 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7140
7141 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7142 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7143 // getting generated.
7144 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7145 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7146
7147 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7148}
7149
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007150/**
7151 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7152 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7153 * that the pointer is hovering over may have a different transform.
7154 */
7155TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007156 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007157
7158 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007159 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7160 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7161 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007162 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7163 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007164 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007165 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7166 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7167 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007168 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7169 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7170 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7171}
7172
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007173class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7174 virtual void SetUp() override {
7175 InputDispatcherTest::SetUp();
7176
Chris Yea209fde2020-07-22 13:54:51 -07007177 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007178 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007179 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7180 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007181 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007182 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007183 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007184
7185 // Set focused application.
7186 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7187
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007188 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007189 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007190 mWindow->consumeFocusEvent(true);
7191 }
7192
7193 virtual void TearDown() override {
7194 InputDispatcherTest::TearDown();
7195 mWindow.clear();
7196 }
7197
7198protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007199 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007200 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007201 sp<FakeWindowHandle> mWindow;
7202 static constexpr PointF WINDOW_LOCATION = {20, 20};
7203
7204 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007206 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007207 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007209 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007210 WINDOW_LOCATION));
7211 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007212
7213 sp<FakeWindowHandle> addSpyWindow() {
7214 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007215 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007216 spy->setTrustedOverlay(true);
7217 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007218 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007219 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007220 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007221 return spy;
7222 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007223};
7224
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007225// Send a tap and respond, which should not cause an ANR.
7226TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7227 tapOnWindow();
7228 mWindow->consumeMotionDown();
7229 mWindow->consumeMotionUp();
7230 ASSERT_TRUE(mDispatcher->waitForIdle());
7231 mFakePolicy->assertNotifyAnrWasNotCalled();
7232}
7233
7234// Send a regular key and respond, which should not cause an ANR.
7235TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007237 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7238 ASSERT_TRUE(mDispatcher->waitForIdle());
7239 mFakePolicy->assertNotifyAnrWasNotCalled();
7240}
7241
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007242TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7243 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007244 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007245 mWindow->consumeFocusEvent(false);
7246
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007247 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007248 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7249 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007250 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007252 // Key will not go to window because we have no focused window.
7253 // The 'no focused window' ANR timer should start instead.
7254
7255 // Now, the focused application goes away.
7256 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7257 // The key should get dropped and there should be no ANR.
7258
7259 ASSERT_TRUE(mDispatcher->waitForIdle());
7260 mFakePolicy->assertNotifyAnrWasNotCalled();
7261}
7262
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007263// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007264// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7265// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007266TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007268 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007269 WINDOW_LOCATION));
7270
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007271 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7272 ASSERT_TRUE(sequenceNum);
7273 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007274 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007275
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007276 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007277 mWindow->consumeMotionEvent(
7278 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007279 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007280 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007281}
7282
7283// Send a key to the app and have the app not respond right away.
7284TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7285 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007287 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7288 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007289 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007290 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007291 ASSERT_TRUE(mDispatcher->waitForIdle());
7292}
7293
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007294// We have a focused application, but no focused window
7295TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007296 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007297 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007298 mWindow->consumeFocusEvent(false);
7299
7300 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007302 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007303 WINDOW_LOCATION));
7304 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7305 mDispatcher->waitForIdle();
7306 mFakePolicy->assertNotifyAnrWasNotCalled();
7307
7308 // Once a focused event arrives, we get an ANR for this application
7309 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7310 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007311 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007312 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007313 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007314 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007315 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007316 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007317 ASSERT_TRUE(mDispatcher->waitForIdle());
7318}
7319
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007320/**
7321 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7322 * there will not be an ANR.
7323 */
7324TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7325 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007326 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007327 mWindow->consumeFocusEvent(false);
7328
7329 KeyEvent event;
7330 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7331 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7332
7333 // Define a valid key down event that is stale (too old).
7334 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007335 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007336 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007337
7338 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7339
7340 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007341 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007342 InputEventInjectionSync::WAIT_FOR_RESULT,
7343 INJECT_EVENT_TIMEOUT, policyFlags);
7344 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7345 << "Injection should fail because the event is stale";
7346
7347 ASSERT_TRUE(mDispatcher->waitForIdle());
7348 mFakePolicy->assertNotifyAnrWasNotCalled();
7349 mWindow->assertNoEvents();
7350}
7351
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007352// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007353// Make sure that we don't notify policy twice about the same ANR.
7354TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007355 const std::chrono::duration appTimeout = 400ms;
7356 mApplication->setDispatchingTimeout(appTimeout);
7357 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7358
Vishnu Nair47074b82020-08-14 11:54:47 -07007359 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007360 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007361 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007362
7363 // Once a focused event arrives, we get an ANR for this application
7364 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7365 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007366 const std::chrono::duration eventInjectionTimeout = 100ms;
7367 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007368 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007369 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007370 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7371 /*allowKeyRepeat=*/false);
7372 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7373 << "result=" << ftl::enum_string(result);
7374 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7375 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7376 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7377 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007378
Vishnu Naire4df8752022-09-08 09:17:55 -07007379 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007380 // ANR should not be raised again. It is up to policy to do that if it desires.
7381 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007382
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007383 // If we now get a focused window, the ANR should stop, but the policy handles that via
7384 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007385 ASSERT_TRUE(mDispatcher->waitForIdle());
7386}
7387
7388// We have a focused application, but no focused window
7389TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007390 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007391 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007392 mWindow->consumeFocusEvent(false);
7393
7394 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007395 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007396
Vishnu Naire4df8752022-09-08 09:17:55 -07007397 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7398 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007399
7400 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007401 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007402 ASSERT_TRUE(mDispatcher->waitForIdle());
7403 mWindow->assertNoEvents();
7404}
7405
7406/**
7407 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7408 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7409 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7410 * the ANR mechanism should still work.
7411 *
7412 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7413 * DOWN event, while not responding on the second one.
7414 */
7415TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7416 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007417 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007418 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7419 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7420 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007421 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007422
7423 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007424 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007425 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7426 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7427 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007428 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007429
7430 // We have now sent down and up. Let's consume first event and then ANR on the second.
7431 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7432 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007433 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434}
7435
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007436// A spy window can receive an ANR
7437TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7438 sp<FakeWindowHandle> spy = addSpyWindow();
7439
7440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007441 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007442 WINDOW_LOCATION));
7443 mWindow->consumeMotionDown();
7444
7445 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7446 ASSERT_TRUE(sequenceNum);
7447 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007448 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007449
7450 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007451 spy->consumeMotionEvent(
7452 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007453 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007454 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007455}
7456
7457// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007458// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007459TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7460 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007461
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007462 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007463 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007464 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007466
7467 // Stuck on the ACTION_UP
7468 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007469 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007470
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007471 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007472 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007473 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7474 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007475
7476 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7477 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007478 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007479 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007480 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007481}
7482
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007483// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007484// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007485TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7486 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007487
7488 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007489 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7490 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007491
7492 mWindow->consumeMotionDown();
7493 // Stuck on the ACTION_UP
7494 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007495 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007496
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007497 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007498 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007499 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7500 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007501
7502 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7503 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007504 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007505 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007506 spy->assertNoEvents();
7507}
7508
7509TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007510 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007511
Prabir Pradhanfb549072023-10-05 19:17:36 +00007512 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007513
7514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007515 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007516 WINDOW_LOCATION));
7517
7518 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7519 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7520 ASSERT_TRUE(consumeSeq);
7521
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007522 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7523 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007524
7525 monitor.finishEvent(*consumeSeq);
7526 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7527
7528 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007529 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007530}
7531
7532// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7533// process events, you don't get an anr. When the window later becomes unresponsive again, you
7534// get an ANR again.
7535// 1. tap -> block on ACTION_UP -> receive ANR
7536// 2. consume all pending events (= queue becomes healthy again)
7537// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7538TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7539 tapOnWindow();
7540
7541 mWindow->consumeMotionDown();
7542 // Block on ACTION_UP
7543 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007544 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007545 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7546 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007547 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007548 mWindow->assertNoEvents();
7549
7550 tapOnWindow();
7551 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007552 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007553 mWindow->consumeMotionUp();
7554
7555 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007556 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007557 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007558 mWindow->assertNoEvents();
7559}
7560
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007561// If a connection remains unresponsive for a while, make sure policy is only notified once about
7562// it.
7563TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007565 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007566 WINDOW_LOCATION));
7567
7568 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007569 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007570 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007571 // 'notifyConnectionUnresponsive' should only be called once per connection
7572 mFakePolicy->assertNotifyAnrWasNotCalled();
7573 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007574 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007575 mWindow->consumeMotionEvent(
7576 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007577 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007578 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007579 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007580 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007581}
7582
7583/**
7584 * 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 -07007585 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007586 *
7587 * Warning!!!
7588 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7589 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007590 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007591 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7592 *
7593 * If that value changes, this test should also change.
7594 */
7595TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7596 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007597 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007598
7599 tapOnWindow();
7600 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7601 ASSERT_TRUE(downSequenceNum);
7602 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7603 ASSERT_TRUE(upSequenceNum);
7604 // Don't finish the events yet, and send a key
7605 // Injection will "succeed" because we will eventually give up and send the key to the focused
7606 // window even if motions are still being processed. But because the injection timeout is short,
7607 // we will receive INJECTION_TIMED_OUT as the result.
7608
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007610 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7611 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007612 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007613 // Key will not be sent to the window, yet, because the window is still processing events
7614 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007615 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7616 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7617 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7618 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007619
7620 std::this_thread::sleep_for(500ms);
7621 // if we wait long enough though, dispatcher will give up, and still send the key
7622 // to the focused window, even though we have not yet finished the motion event
7623 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7624 mWindow->finishEvent(*downSequenceNum);
7625 mWindow->finishEvent(*upSequenceNum);
7626}
7627
7628/**
7629 * If a window is processing a motion event, and then a key event comes in, the key event should
7630 * not go to the focused window until the motion is processed.
7631 * If then a new motion comes in, then the pending key event should be going to the currently
7632 * focused window right away.
7633 */
7634TEST_F(InputDispatcherSingleWindowAnr,
7635 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7636 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007637 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007638
7639 tapOnWindow();
7640 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7641 ASSERT_TRUE(downSequenceNum);
7642 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7643 ASSERT_TRUE(upSequenceNum);
7644 // Don't finish the events yet, and send a key
7645 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007647 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7648 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007649 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007650 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7651 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7652 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7653 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007654
7655 // Now tap down again. It should cause the pending key to go to the focused window right away.
7656 tapOnWindow();
7657 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7658 // the other events yet. We can finish events in any order.
7659 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7660 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7661 mWindow->consumeMotionDown();
7662 mWindow->consumeMotionUp();
7663 mWindow->assertNoEvents();
7664}
7665
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007666/**
7667 * Send an event to the app and have the app not respond right away.
7668 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7669 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7670 * At some point, the window becomes responsive again.
7671 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7672 */
7673TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7675 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7676 .build());
7677
7678 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7679 ASSERT_TRUE(sequenceNum);
7680 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7681 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7682
7683 mWindow->finishEvent(*sequenceNum);
7684 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7685 ASSERT_TRUE(mDispatcher->waitForIdle());
7686 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7687
7688 // Now that the window is responsive, let's continue the gesture.
7689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7690 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7691 .build());
7692
7693 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7694 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7695 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7696 .build());
7697
7698 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7699 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7700 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7701 .build());
7702 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7703 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7704 .build());
7705 // We already canceled this pointer, so the window shouldn't get any new events.
7706 mWindow->assertNoEvents();
7707
7708 // Start another one.
7709 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7710 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7711 .build());
7712 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7713}
7714
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007715class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7716 virtual void SetUp() override {
7717 InputDispatcherTest::SetUp();
7718
Chris Yea209fde2020-07-22 13:54:51 -07007719 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007720 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007721 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7722 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007723 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007724 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007725 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007726
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007727 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7728 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007729 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007730 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007731
7732 // Set focused application.
7733 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007734 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007735
7736 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007737 mDispatcher->onWindowInfosChanged(
7738 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007739 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007740 mFocusedWindow->consumeFocusEvent(true);
7741 }
7742
7743 virtual void TearDown() override {
7744 InputDispatcherTest::TearDown();
7745
7746 mUnfocusedWindow.clear();
7747 mFocusedWindow.clear();
7748 }
7749
7750protected:
Chris Yea209fde2020-07-22 13:54:51 -07007751 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007752 sp<FakeWindowHandle> mUnfocusedWindow;
7753 sp<FakeWindowHandle> mFocusedWindow;
7754 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7755 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7756 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7757
7758 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7759
7760 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7761
7762private:
7763 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007765 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007766 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007768 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007769 location));
7770 }
7771};
7772
7773// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7774// should be ANR'd first.
7775TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007777 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007778 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007780 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007781 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007782 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007783 // We consumed all events, so no ANR
7784 ASSERT_TRUE(mDispatcher->waitForIdle());
7785 mFakePolicy->assertNotifyAnrWasNotCalled();
7786
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007788 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007789 FOCUSED_WINDOW_LOCATION));
7790 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7791 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007792
7793 const std::chrono::duration timeout =
7794 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007795 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007796 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7797 // sequence to make it consistent
7798 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007799 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007800 mFocusedWindow->consumeMotionDown();
7801 // This cancel is generated because the connection was unresponsive
7802 mFocusedWindow->consumeMotionCancel();
7803 mFocusedWindow->assertNoEvents();
7804 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007805 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007806 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7807 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007808 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007809}
7810
7811// If we have 2 windows with identical timeouts that are both unresponsive,
7812// it doesn't matter which order they should have ANR.
7813// But we should receive ANR for both.
7814TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7815 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007816 mUnfocusedWindow->setDispatchingTimeout(
7817 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007818 mDispatcher->onWindowInfosChanged(
7819 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007820
7821 tapOnFocusedWindow();
7822 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007823 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007824 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7825 mFocusedWindow->getDispatchingTimeout(
7826 DISPATCHING_TIMEOUT)),
7827 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7828
7829 ASSERT_THAT(anrConnectionTokens,
7830 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7831 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007832
7833 ASSERT_TRUE(mDispatcher->waitForIdle());
7834 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007835
7836 mFocusedWindow->consumeMotionDown();
7837 mFocusedWindow->consumeMotionUp();
7838 mUnfocusedWindow->consumeMotionOutside();
7839
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007840 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7841 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007842
7843 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007844 ASSERT_THAT(responsiveTokens,
7845 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7846 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007847 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007848}
7849
7850// If a window is already not responding, the second tap on the same window should be ignored.
7851// We should also log an error to account for the dropped event (not tested here).
7852// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7853TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7854 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007855 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007856 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007857 // Receive the events, but don't respond
7858 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7859 ASSERT_TRUE(downEventSequenceNum);
7860 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7861 ASSERT_TRUE(upEventSequenceNum);
7862 const std::chrono::duration timeout =
7863 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007864 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007865
7866 // Tap once again
7867 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007868 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007870 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007871 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007872 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007873 FOCUSED_WINDOW_LOCATION));
7874 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7875 // valid touch target
7876 mUnfocusedWindow->assertNoEvents();
7877
7878 // Consume the first tap
7879 mFocusedWindow->finishEvent(*downEventSequenceNum);
7880 mFocusedWindow->finishEvent(*upEventSequenceNum);
7881 ASSERT_TRUE(mDispatcher->waitForIdle());
7882 // The second tap did not go to the focused window
7883 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007884 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007885 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7886 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007887 mFakePolicy->assertNotifyAnrWasNotCalled();
7888}
7889
7890// If you tap outside of all windows, there will not be ANR
7891TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007892 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007894 LOCATION_OUTSIDE_ALL_WINDOWS));
7895 ASSERT_TRUE(mDispatcher->waitForIdle());
7896 mFakePolicy->assertNotifyAnrWasNotCalled();
7897}
7898
7899// Since the focused window is paused, tapping on it should not produce any events
7900TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7901 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007902 mDispatcher->onWindowInfosChanged(
7903 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007904
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007905 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007906 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007907 FOCUSED_WINDOW_LOCATION));
7908
7909 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7910 ASSERT_TRUE(mDispatcher->waitForIdle());
7911 // Should not ANR because the window is paused, and touches shouldn't go to it
7912 mFakePolicy->assertNotifyAnrWasNotCalled();
7913
7914 mFocusedWindow->assertNoEvents();
7915 mUnfocusedWindow->assertNoEvents();
7916}
7917
7918/**
7919 * 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 -07007920 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007921 * If a different window becomes focused at this time, the key should go to that window instead.
7922 *
7923 * Warning!!!
7924 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7925 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007926 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007927 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7928 *
7929 * If that value changes, this test should also change.
7930 */
7931TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7932 // Set a long ANR timeout to prevent it from triggering
7933 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007934 mDispatcher->onWindowInfosChanged(
7935 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007936
7937 tapOnUnfocusedWindow();
7938 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7939 ASSERT_TRUE(downSequenceNum);
7940 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7941 ASSERT_TRUE(upSequenceNum);
7942 // Don't finish the events yet, and send a key
7943 // Injection will succeed because we will eventually give up and send the key to the focused
7944 // window even if motions are still being processed.
7945
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007946 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007947 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7948 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007950 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007951 // and the key remains pending, waiting for the touch events to be processed.
7952 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7953 // under the hood.
7954 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7955 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007956
7957 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007958 mFocusedWindow->setFocusable(false);
7959 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007960 mDispatcher->onWindowInfosChanged(
7961 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007962 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007963
7964 // Focus events should precede the key events
7965 mUnfocusedWindow->consumeFocusEvent(true);
7966 mFocusedWindow->consumeFocusEvent(false);
7967
7968 // Finish the tap events, which should unblock dispatcher
7969 mUnfocusedWindow->finishEvent(*downSequenceNum);
7970 mUnfocusedWindow->finishEvent(*upSequenceNum);
7971
7972 // Now that all queues are cleared and no backlog in the connections, the key event
7973 // can finally go to the newly focused "mUnfocusedWindow".
7974 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7975 mFocusedWindow->assertNoEvents();
7976 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007977 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007978}
7979
7980// When the touch stream is split across 2 windows, and one of them does not respond,
7981// then ANR should be raised and the touch should be canceled for the unresponsive window.
7982// The other window should not be affected by that.
7983TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7984 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007985 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7986 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7987 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007988 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007989 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007990
7991 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007992 mDispatcher->notifyMotion(
7993 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7994 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007995
7996 const std::chrono::duration timeout =
7997 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007998 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007999
8000 mUnfocusedWindow->consumeMotionDown();
8001 mFocusedWindow->consumeMotionDown();
8002 // Focused window may or may not receive ACTION_MOVE
8003 // But it should definitely receive ACTION_CANCEL due to the ANR
8004 InputEvent* event;
8005 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8006 ASSERT_TRUE(moveOrCancelSequenceNum);
8007 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8008 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008009 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008010 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8011 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8012 mFocusedWindow->consumeMotionCancel();
8013 } else {
8014 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8015 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008016 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008017 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8018 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008019
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008020 mUnfocusedWindow->assertNoEvents();
8021 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008022 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008023}
8024
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008025/**
8026 * If we have no focused window, and a key comes in, we start the ANR timer.
8027 * The focused application should add a focused window before the timer runs out to prevent ANR.
8028 *
8029 * If the user touches another application during this time, the key should be dropped.
8030 * Next, if a new focused window comes in, without toggling the focused application,
8031 * then no ANR should occur.
8032 *
8033 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8034 * but in some cases the policy may not update the focused application.
8035 */
8036TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8037 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8038 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008039 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008040 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8041 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8042 mFocusedWindow->setFocusable(false);
8043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008044 mDispatcher->onWindowInfosChanged(
8045 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008046 mFocusedWindow->consumeFocusEvent(false);
8047
8048 // Send a key. The ANR timer should start because there is no focused window.
8049 // 'focusedApplication' will get blamed if this timer completes.
8050 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008051 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008052 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8053 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008054 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008056
8057 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8058 // then the injected touches won't cause the focused event to get dropped.
8059 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8060 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8061 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8062 // For this test, it means that the key would get delivered to the window once it becomes
8063 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008064 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008065
8066 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008067 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8068 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8069 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008070
8071 // We do not consume the motion right away, because that would require dispatcher to first
8072 // process (== drop) the key event, and by that time, ANR will be raised.
8073 // Set the focused window first.
8074 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008075 mDispatcher->onWindowInfosChanged(
8076 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008077 setFocusedWindow(mFocusedWindow);
8078 mFocusedWindow->consumeFocusEvent(true);
8079 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8080 // to another application. This could be a bug / behaviour in the policy.
8081
8082 mUnfocusedWindow->consumeMotionDown();
8083
8084 ASSERT_TRUE(mDispatcher->waitForIdle());
8085 // Should not ANR because we actually have a focused window. It was just added too slowly.
8086 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8087}
8088
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008089// These tests ensure we cannot send touch events to a window that's positioned behind a window
8090// that has feature NO_INPUT_CHANNEL.
8091// Layout:
8092// Top (closest to user)
8093// mNoInputWindow (above all windows)
8094// mBottomWindow
8095// Bottom (furthest from user)
8096class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8097 virtual void SetUp() override {
8098 InputDispatcherTest::SetUp();
8099
8100 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008101 mNoInputWindow =
8102 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8103 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008104 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008105 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008106 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8107 // It's perfectly valid for this window to not have an associated input channel
8108
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008109 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8110 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008111 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8112
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008113 mDispatcher->onWindowInfosChanged(
8114 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008115 }
8116
8117protected:
8118 std::shared_ptr<FakeApplicationHandle> mApplication;
8119 sp<FakeWindowHandle> mNoInputWindow;
8120 sp<FakeWindowHandle> mBottomWindow;
8121};
8122
8123TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8124 PointF touchedPoint = {10, 10};
8125
Prabir Pradhan678438e2023-04-13 19:32:51 +00008126 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8127 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8128 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008129
8130 mNoInputWindow->assertNoEvents();
8131 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8132 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8133 // and therefore should prevent mBottomWindow from receiving touches
8134 mBottomWindow->assertNoEvents();
8135}
8136
8137/**
8138 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8139 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8140 */
8141TEST_F(InputDispatcherMultiWindowOcclusionTests,
8142 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008143 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8144 "Window with input channel and NO_INPUT_CHANNEL",
8145 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008146
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008147 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008148 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008149 mDispatcher->onWindowInfosChanged(
8150 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008151
8152 PointF touchedPoint = {10, 10};
8153
Prabir Pradhan678438e2023-04-13 19:32:51 +00008154 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8155 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8156 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008157
8158 mNoInputWindow->assertNoEvents();
8159 mBottomWindow->assertNoEvents();
8160}
8161
Vishnu Nair958da932020-08-21 17:12:37 -07008162class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8163protected:
8164 std::shared_ptr<FakeApplicationHandle> mApp;
8165 sp<FakeWindowHandle> mWindow;
8166 sp<FakeWindowHandle> mMirror;
8167
8168 virtual void SetUp() override {
8169 InputDispatcherTest::SetUp();
8170 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008171 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8172 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8173 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008174 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8175 mWindow->setFocusable(true);
8176 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008177 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008178 }
8179};
8180
8181TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8182 // Request focus on a mirrored window
8183 setFocusedWindow(mMirror);
8184
8185 // window gets focused
8186 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008188 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008189 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8190}
8191
8192// A focused & mirrored window remains focused only if the window and its mirror are both
8193// focusable.
8194TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8195 setFocusedWindow(mMirror);
8196
8197 // window gets focused
8198 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008200 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008201 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008203 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008204 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8205
8206 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008207 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008208
8209 // window loses focus since one of the windows associated with the token in not focusable
8210 mWindow->consumeFocusEvent(false);
8211
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008212 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008213 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008214 mWindow->assertNoEvents();
8215}
8216
8217// A focused & mirrored window remains focused until the window and its mirror both become
8218// invisible.
8219TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8220 setFocusedWindow(mMirror);
8221
8222 // window gets focused
8223 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008225 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008226 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008228 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008229 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8230
8231 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008232 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008233
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008235 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008236 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008238 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008239 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8240
8241 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008242 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008243
8244 // window loses focus only after all windows associated with the token become invisible.
8245 mWindow->consumeFocusEvent(false);
8246
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008247 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008248 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008249 mWindow->assertNoEvents();
8250}
8251
8252// A focused & mirrored window remains focused until both windows are removed.
8253TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8254 setFocusedWindow(mMirror);
8255
8256 // window gets focused
8257 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008259 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008260 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008262 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008263 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8264
8265 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008266 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008267
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008269 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008270 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008272 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008273 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8274
8275 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008276 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008277 mWindow->consumeFocusEvent(false);
8278
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008279 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008280 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008281 mWindow->assertNoEvents();
8282}
8283
8284// Focus request can be pending until one window becomes visible.
8285TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8286 // Request focus on an invisible mirror.
8287 mWindow->setVisible(false);
8288 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008289 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008290 setFocusedWindow(mMirror);
8291
8292 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008294 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8295 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008296
8297 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008298 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008299
8300 // window gets focused
8301 mWindow->consumeFocusEvent(true);
8302 // window gets the pending key event
8303 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8304}
Prabir Pradhan99987712020-11-10 18:43:05 -08008305
8306class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8307protected:
8308 std::shared_ptr<FakeApplicationHandle> mApp;
8309 sp<FakeWindowHandle> mWindow;
8310 sp<FakeWindowHandle> mSecondWindow;
8311
8312 void SetUp() override {
8313 InputDispatcherTest::SetUp();
8314 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008315 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008316 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008317 mSecondWindow =
8318 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008319 mSecondWindow->setFocusable(true);
8320
8321 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008322 mDispatcher->onWindowInfosChanged(
8323 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008324
8325 setFocusedWindow(mWindow);
8326 mWindow->consumeFocusEvent(true);
8327 }
8328
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008329 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008330 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008331 }
8332
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008333 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8334 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008335 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008336 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8337 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008338 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008339 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008340 }
8341};
8342
8343TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8344 // Ensure that capture cannot be obtained for unfocused windows.
8345 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8346 mFakePolicy->assertSetPointerCaptureNotCalled();
8347 mSecondWindow->assertNoEvents();
8348
8349 // Ensure that capture can be enabled from the focus window.
8350 requestAndVerifyPointerCapture(mWindow, true);
8351
8352 // Ensure that capture cannot be disabled from a window that does not have capture.
8353 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8354 mFakePolicy->assertSetPointerCaptureNotCalled();
8355
8356 // Ensure that capture can be disabled from the window with capture.
8357 requestAndVerifyPointerCapture(mWindow, false);
8358}
8359
8360TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008361 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008362
8363 setFocusedWindow(mSecondWindow);
8364
8365 // Ensure that the capture disabled event was sent first.
8366 mWindow->consumeCaptureEvent(false);
8367 mWindow->consumeFocusEvent(false);
8368 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008369 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008370
8371 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008372 notifyPointerCaptureChanged({});
8373 notifyPointerCaptureChanged(request);
8374 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008375 mWindow->assertNoEvents();
8376 mSecondWindow->assertNoEvents();
8377 mFakePolicy->assertSetPointerCaptureNotCalled();
8378}
8379
8380TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008381 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008382
8383 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008384 notifyPointerCaptureChanged({});
8385 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008386
8387 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008388 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008389 mWindow->consumeCaptureEvent(false);
8390 mWindow->assertNoEvents();
8391}
8392
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008393TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8394 requestAndVerifyPointerCapture(mWindow, true);
8395
8396 // The first window loses focus.
8397 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008398 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008399 mWindow->consumeCaptureEvent(false);
8400
8401 // Request Pointer Capture from the second window before the notification from InputReader
8402 // arrives.
8403 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008404 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008405
8406 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008407 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008408
8409 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008410 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008411
8412 mSecondWindow->consumeFocusEvent(true);
8413 mSecondWindow->consumeCaptureEvent(true);
8414}
8415
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008416TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8417 // App repeatedly enables and disables capture.
8418 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8419 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8420 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8421 mFakePolicy->assertSetPointerCaptureCalled(false);
8422 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8423 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8424
8425 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8426 // first request is now stale, this should do nothing.
8427 notifyPointerCaptureChanged(firstRequest);
8428 mWindow->assertNoEvents();
8429
8430 // InputReader notifies that the second request was enabled.
8431 notifyPointerCaptureChanged(secondRequest);
8432 mWindow->consumeCaptureEvent(true);
8433}
8434
Prabir Pradhan7092e262022-05-03 16:51:09 +00008435TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8436 requestAndVerifyPointerCapture(mWindow, true);
8437
8438 // App toggles pointer capture off and on.
8439 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8440 mFakePolicy->assertSetPointerCaptureCalled(false);
8441
8442 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8443 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8444
8445 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8446 // preceding "disable" request.
8447 notifyPointerCaptureChanged(enableRequest);
8448
8449 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8450 // any notifications.
8451 mWindow->assertNoEvents();
8452}
8453
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008454/**
8455 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8456 * mouse movements don't affect the previous mouse hovering state.
8457 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8458 * HOVER_MOVE events).
8459 */
8460TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8461 // Mouse hover on the window
8462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8463 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8464 .build());
8465 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8466 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8467 .build());
8468
8469 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8470 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8471
8472 // Start pointer capture
8473 requestAndVerifyPointerCapture(mWindow, true);
8474
8475 // Send some relative mouse movements and receive them in the window.
8476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8477 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8478 .build());
8479 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8480 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8481
8482 // Stop pointer capture
8483 requestAndVerifyPointerCapture(mWindow, false);
8484
8485 // Continue hovering on the window
8486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8487 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8488 .build());
8489 mWindow->consumeMotionEvent(
8490 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8491
8492 mWindow->assertNoEvents();
8493}
8494
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008495class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8496protected:
8497 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008498
8499 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8500 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8501
8502 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8503 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8504
8505 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8506 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8507 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8508 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8509 MAXIMUM_OBSCURING_OPACITY);
8510
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008511 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8512 static constexpr gui::Uid APP_B_UID{10002};
8513 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008514
8515 sp<FakeWindowHandle> mTouchWindow;
8516
8517 virtual void SetUp() override {
8518 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008519 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008520 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8521 }
8522
8523 virtual void TearDown() override {
8524 InputDispatcherTest::TearDown();
8525 mTouchWindow.clear();
8526 }
8527
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008528 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008529 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008530 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008531 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008532 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008533 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008534 return window;
8535 }
8536
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008537 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008538 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8539 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008540 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008541 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008542 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008543 return window;
8544 }
8545
8546 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008547 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8548 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8549 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008550 }
8551};
8552
8553TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008554 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008555 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008556 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008557
8558 touch();
8559
8560 mTouchWindow->assertNoEvents();
8561}
8562
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008563TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008564 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8565 const sp<FakeWindowHandle>& w =
8566 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008567 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008568
8569 touch();
8570
8571 mTouchWindow->assertNoEvents();
8572}
8573
8574TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008575 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8576 const sp<FakeWindowHandle>& w =
8577 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008578 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008579
8580 touch();
8581
8582 w->assertNoEvents();
8583}
8584
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008585TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008586 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008587 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008588
8589 touch();
8590
8591 mTouchWindow->consumeAnyMotionDown();
8592}
8593
8594TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008595 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008596 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008597 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008598 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008599
8600 touch({PointF{100, 100}});
8601
8602 mTouchWindow->consumeAnyMotionDown();
8603}
8604
8605TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008606 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008607 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008608 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008609
8610 touch();
8611
8612 mTouchWindow->consumeAnyMotionDown();
8613}
8614
8615TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8616 const sp<FakeWindowHandle>& w =
8617 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008618 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008619
8620 touch();
8621
8622 mTouchWindow->consumeAnyMotionDown();
8623}
8624
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008625TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8626 const sp<FakeWindowHandle>& w =
8627 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008628 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008629
8630 touch();
8631
8632 w->assertNoEvents();
8633}
8634
8635/**
8636 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8637 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8638 * window, the occluding window will still receive ACTION_OUTSIDE event.
8639 */
8640TEST_F(InputDispatcherUntrustedTouchesTest,
8641 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8642 const sp<FakeWindowHandle>& w =
8643 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008644 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008645 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008646
8647 touch();
8648
8649 w->consumeMotionOutside();
8650}
8651
8652TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8653 const sp<FakeWindowHandle>& w =
8654 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008655 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008656 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008657
8658 touch();
8659
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008660 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008661}
8662
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008663TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008664 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008665 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8666 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008667 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008668
8669 touch();
8670
8671 mTouchWindow->consumeAnyMotionDown();
8672}
8673
8674TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8675 const sp<FakeWindowHandle>& w =
8676 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8677 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008678 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008679
8680 touch();
8681
8682 mTouchWindow->consumeAnyMotionDown();
8683}
8684
8685TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008686 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008687 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8688 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008689 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008690
8691 touch();
8692
8693 mTouchWindow->assertNoEvents();
8694}
8695
8696TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8697 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8698 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008699 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8700 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008701 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008702 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8703 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008704 mDispatcher->onWindowInfosChanged(
8705 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008706
8707 touch();
8708
8709 mTouchWindow->assertNoEvents();
8710}
8711
8712TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8713 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8714 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008715 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8716 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008717 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008718 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8719 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008720 mDispatcher->onWindowInfosChanged(
8721 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008722
8723 touch();
8724
8725 mTouchWindow->consumeAnyMotionDown();
8726}
8727
8728TEST_F(InputDispatcherUntrustedTouchesTest,
8729 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8730 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008731 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8732 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008733 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008734 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8735 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008736 mDispatcher->onWindowInfosChanged(
8737 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008738
8739 touch();
8740
8741 mTouchWindow->consumeAnyMotionDown();
8742}
8743
8744TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8745 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008746 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8747 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008748 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008749 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8750 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008751 mDispatcher->onWindowInfosChanged(
8752 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008753
8754 touch();
8755
8756 mTouchWindow->assertNoEvents();
8757}
8758
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008759TEST_F(InputDispatcherUntrustedTouchesTest,
8760 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8761 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008762 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8763 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008764 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008765 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8766 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008767 mDispatcher->onWindowInfosChanged(
8768 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008769
8770 touch();
8771
8772 mTouchWindow->assertNoEvents();
8773}
8774
8775TEST_F(InputDispatcherUntrustedTouchesTest,
8776 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8777 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008778 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8779 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008780 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008781 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8782 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008783 mDispatcher->onWindowInfosChanged(
8784 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008785
8786 touch();
8787
8788 mTouchWindow->consumeAnyMotionDown();
8789}
8790
8791TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8792 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008793 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8794 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008795 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008796
8797 touch();
8798
8799 mTouchWindow->consumeAnyMotionDown();
8800}
8801
8802TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8803 const sp<FakeWindowHandle>& w =
8804 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008805 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008806
8807 touch();
8808
8809 mTouchWindow->consumeAnyMotionDown();
8810}
8811
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008812TEST_F(InputDispatcherUntrustedTouchesTest,
8813 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8814 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8815 const sp<FakeWindowHandle>& w =
8816 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008817 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008818
8819 touch();
8820
8821 mTouchWindow->assertNoEvents();
8822}
8823
8824TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8825 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8826 const sp<FakeWindowHandle>& w =
8827 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008828 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008829
8830 touch();
8831
8832 mTouchWindow->consumeAnyMotionDown();
8833}
8834
8835TEST_F(InputDispatcherUntrustedTouchesTest,
8836 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8837 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8838 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008839 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8840 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008841 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008842
8843 touch();
8844
8845 mTouchWindow->consumeAnyMotionDown();
8846}
8847
8848TEST_F(InputDispatcherUntrustedTouchesTest,
8849 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8850 const sp<FakeWindowHandle>& w1 =
8851 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8852 OPACITY_BELOW_THRESHOLD);
8853 const sp<FakeWindowHandle>& w2 =
8854 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8855 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008856 mDispatcher->onWindowInfosChanged(
8857 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008858
8859 touch();
8860
8861 mTouchWindow->assertNoEvents();
8862}
8863
8864/**
8865 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8866 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8867 * (which alone would result in allowing touches) does not affect the blocking behavior.
8868 */
8869TEST_F(InputDispatcherUntrustedTouchesTest,
8870 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8871 const sp<FakeWindowHandle>& wB =
8872 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8873 OPACITY_BELOW_THRESHOLD);
8874 const sp<FakeWindowHandle>& wC =
8875 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8876 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008877 mDispatcher->onWindowInfosChanged(
8878 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008879
8880 touch();
8881
8882 mTouchWindow->assertNoEvents();
8883}
8884
8885/**
8886 * This test is testing that a window from a different UID but with same application token doesn't
8887 * block the touch. Apps can share the application token for close UI collaboration for example.
8888 */
8889TEST_F(InputDispatcherUntrustedTouchesTest,
8890 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8891 const sp<FakeWindowHandle>& w =
8892 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8893 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008894 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008895
8896 touch();
8897
8898 mTouchWindow->consumeAnyMotionDown();
8899}
8900
arthurhungb89ccb02020-12-30 16:19:01 +08008901class InputDispatcherDragTests : public InputDispatcherTest {
8902protected:
8903 std::shared_ptr<FakeApplicationHandle> mApp;
8904 sp<FakeWindowHandle> mWindow;
8905 sp<FakeWindowHandle> mSecondWindow;
8906 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008907 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008908 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8909 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008910
8911 void SetUp() override {
8912 InputDispatcherTest::SetUp();
8913 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008914 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008915 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008916
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008917 mSecondWindow =
8918 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008919 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008920
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008921 mSpyWindow =
8922 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008923 mSpyWindow->setSpy(true);
8924 mSpyWindow->setTrustedOverlay(true);
8925 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8926
arthurhungb89ccb02020-12-30 16:19:01 +08008927 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008928 mDispatcher->onWindowInfosChanged(
8929 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8930 {},
8931 0,
8932 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008933 }
8934
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008935 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8936 switch (fromSource) {
8937 case AINPUT_SOURCE_TOUCHSCREEN:
8938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008939 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008940 ADISPLAY_ID_DEFAULT, {50, 50}))
8941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8942 break;
8943 case AINPUT_SOURCE_STYLUS:
8944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008945 injectMotionEvent(*mDispatcher,
8946 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8947 AINPUT_SOURCE_STYLUS)
8948 .buttonState(
8949 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8950 .pointer(PointerBuilder(0, ToolType::STYLUS)
8951 .x(50)
8952 .y(50))
8953 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008954 break;
8955 case AINPUT_SOURCE_MOUSE:
8956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008957 injectMotionEvent(*mDispatcher,
8958 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8959 AINPUT_SOURCE_MOUSE)
8960 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8961 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8962 ToolType::MOUSE)
8963 .x(50)
8964 .y(50))
8965 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008966 break;
8967 default:
8968 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8969 }
arthurhungb89ccb02020-12-30 16:19:01 +08008970
8971 // Window should receive motion event.
8972 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008973 // Spy window should also receive motion event
8974 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008975 }
8976
8977 // Start performing drag, we will create a drag window and transfer touch to it.
8978 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8979 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008980 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008981 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008982 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008983 }
arthurhungb89ccb02020-12-30 16:19:01 +08008984
8985 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008986 mDragWindow =
8987 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008988 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008989 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8990 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8991 {},
8992 0,
8993 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008994
8995 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008996 bool transferred =
8997 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008998 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008999 if (transferred) {
9000 mWindow->consumeMotionCancel();
9001 mDragWindow->consumeMotionDown();
9002 }
9003 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009004 }
9005};
9006
9007TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009008 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009009
9010 // Move on window.
9011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009012 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009013 ADISPLAY_ID_DEFAULT, {50, 50}))
9014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9015 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9016 mWindow->consumeDragEvent(false, 50, 50);
9017 mSecondWindow->assertNoEvents();
9018
9019 // Move to another window.
9020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009021 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009022 ADISPLAY_ID_DEFAULT, {150, 50}))
9023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9024 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9025 mWindow->consumeDragEvent(true, 150, 50);
9026 mSecondWindow->consumeDragEvent(false, 50, 50);
9027
9028 // Move back to original window.
9029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009030 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009031 ADISPLAY_ID_DEFAULT, {50, 50}))
9032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9033 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9034 mWindow->consumeDragEvent(false, 50, 50);
9035 mSecondWindow->consumeDragEvent(true, -50, 50);
9036
9037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009038 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9039 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9041 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9042 mWindow->assertNoEvents();
9043 mSecondWindow->assertNoEvents();
9044}
9045
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009046TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009047 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009048
9049 // No cancel event after drag start
9050 mSpyWindow->assertNoEvents();
9051
9052 const MotionEvent secondFingerDownEvent =
9053 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9054 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009055 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9056 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009057 .build();
9058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009059 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009060 InputEventInjectionSync::WAIT_FOR_RESULT))
9061 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9062
9063 // Receives cancel for first pointer after next pointer down
9064 mSpyWindow->consumeMotionCancel();
9065 mSpyWindow->consumeMotionDown();
9066
9067 mSpyWindow->assertNoEvents();
9068}
9069
arthurhungf452d0b2021-01-06 00:19:52 +08009070TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009071 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009072
9073 // Move on window.
9074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009075 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009076 ADISPLAY_ID_DEFAULT, {50, 50}))
9077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9078 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9079 mWindow->consumeDragEvent(false, 50, 50);
9080 mSecondWindow->assertNoEvents();
9081
9082 // Move to another window.
9083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009084 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009085 ADISPLAY_ID_DEFAULT, {150, 50}))
9086 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9087 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9088 mWindow->consumeDragEvent(true, 150, 50);
9089 mSecondWindow->consumeDragEvent(false, 50, 50);
9090
9091 // drop to another window.
9092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009093 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009094 {150, 50}))
9095 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9096 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009097 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009098 mWindow->assertNoEvents();
9099 mSecondWindow->assertNoEvents();
9100}
9101
arthurhung6d4bed92021-03-17 11:59:33 +08009102TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009103 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009104
9105 // Move on window and keep button pressed.
9106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009107 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009108 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9109 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009110 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009111 .build()))
9112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9113 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9114 mWindow->consumeDragEvent(false, 50, 50);
9115 mSecondWindow->assertNoEvents();
9116
9117 // Move to another window and release button, expect to drop item.
9118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009119 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009120 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9121 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009122 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009123 .build()))
9124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9125 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9126 mWindow->assertNoEvents();
9127 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009128 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009129
9130 // nothing to the window.
9131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009132 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009133 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9134 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009135 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009136 .build()))
9137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9138 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9139 mWindow->assertNoEvents();
9140 mSecondWindow->assertNoEvents();
9141}
9142
Arthur Hung54745652022-04-20 07:17:41 +00009143TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009144 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009145
9146 // Set second window invisible.
9147 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009148 mDispatcher->onWindowInfosChanged(
9149 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009150
9151 // Move on window.
9152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009153 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009154 ADISPLAY_ID_DEFAULT, {50, 50}))
9155 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9156 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9157 mWindow->consumeDragEvent(false, 50, 50);
9158 mSecondWindow->assertNoEvents();
9159
9160 // Move to another window.
9161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009162 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009163 ADISPLAY_ID_DEFAULT, {150, 50}))
9164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9165 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9166 mWindow->consumeDragEvent(true, 150, 50);
9167 mSecondWindow->assertNoEvents();
9168
9169 // drop to another window.
9170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009171 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009172 {150, 50}))
9173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9174 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009175 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009176 mWindow->assertNoEvents();
9177 mSecondWindow->assertNoEvents();
9178}
9179
Arthur Hung54745652022-04-20 07:17:41 +00009180TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009181 // Ensure window could track pointerIds if it didn't support split touch.
9182 mWindow->setPreventSplitting(true);
9183
Arthur Hung54745652022-04-20 07:17:41 +00009184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009185 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009186 {50, 50}))
9187 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9188 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9189
9190 const MotionEvent secondFingerDownEvent =
9191 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9192 .displayId(ADISPLAY_ID_DEFAULT)
9193 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9195 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009196 .build();
9197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009198 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009199 InputEventInjectionSync::WAIT_FOR_RESULT))
9200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009201 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009202
9203 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009204 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009205}
9206
9207TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9208 // First down on second window.
9209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009210 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009211 {150, 50}))
9212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9213
9214 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9215
9216 // Second down on first window.
9217 const MotionEvent secondFingerDownEvent =
9218 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9219 .displayId(ADISPLAY_ID_DEFAULT)
9220 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009221 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9222 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009223 .build();
9224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009225 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009226 InputEventInjectionSync::WAIT_FOR_RESULT))
9227 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9228 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9229
9230 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009231 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009232
9233 // Move on window.
9234 const MotionEvent secondFingerMoveEvent =
9235 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, 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, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009242 InputEventInjectionSync::WAIT_FOR_RESULT));
9243 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9244 mWindow->consumeDragEvent(false, 50, 50);
9245 mSecondWindow->consumeMotionMove();
9246
9247 // Release the drag pointer should perform drop.
9248 const MotionEvent secondFingerUpEvent =
9249 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9250 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009251 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9252 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009253 .build();
9254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009255 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009256 InputEventInjectionSync::WAIT_FOR_RESULT));
9257 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009258 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009259 mWindow->assertNoEvents();
9260 mSecondWindow->consumeMotionMove();
9261}
9262
Arthur Hung3915c1f2022-05-31 07:17:17 +00009263TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009264 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009265
9266 // Update window of second display.
9267 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009268 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009269 mDispatcher->onWindowInfosChanged(
9270 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9271 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9272 {},
9273 0,
9274 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009275
9276 // Let second display has a touch state.
9277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009278 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009279 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9280 AINPUT_SOURCE_TOUCHSCREEN)
9281 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009282 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009283 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009284 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009285 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009286 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009287 mDispatcher->onWindowInfosChanged(
9288 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9289 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9290 {},
9291 0,
9292 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009293
9294 // Move on window.
9295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009296 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009297 ADISPLAY_ID_DEFAULT, {50, 50}))
9298 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9299 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9300 mWindow->consumeDragEvent(false, 50, 50);
9301 mSecondWindow->assertNoEvents();
9302
9303 // Move to another window.
9304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009305 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009306 ADISPLAY_ID_DEFAULT, {150, 50}))
9307 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9308 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9309 mWindow->consumeDragEvent(true, 150, 50);
9310 mSecondWindow->consumeDragEvent(false, 50, 50);
9311
9312 // drop to another window.
9313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009314 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009315 {150, 50}))
9316 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9317 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009318 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009319 mWindow->assertNoEvents();
9320 mSecondWindow->assertNoEvents();
9321}
9322
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009323TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9324 startDrag(true, AINPUT_SOURCE_MOUSE);
9325 // Move on 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(50)
9332 .y(50))
9333 .build()))
9334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9335 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9336 mWindow->consumeDragEvent(false, 50, 50);
9337 mSecondWindow->assertNoEvents();
9338
9339 // Move 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_MOVE, AINPUT_SOURCE_MOUSE)
9343 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
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->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9350 mWindow->consumeDragEvent(true, 150, 50);
9351 mSecondWindow->consumeDragEvent(false, 50, 50);
9352
9353 // drop to another window.
9354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009355 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009356 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9357 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009358 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009359 .x(150)
9360 .y(50))
9361 .build()))
9362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9363 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009364 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009365 mWindow->assertNoEvents();
9366 mSecondWindow->assertNoEvents();
9367}
9368
Linnan Li5af92f92023-07-14 14:36:22 +08009369/**
9370 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
9371 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
9372 */
9373TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
9374 // Down on second window
9375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9376 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9377 {150, 50}))
9378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9379
9380 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
9381 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
9382
9383 // Down on first window
9384 const MotionEvent secondFingerDownEvent =
9385 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9386 .displayId(ADISPLAY_ID_DEFAULT)
9387 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9388 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9389 .build();
9390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9391 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9392 InputEventInjectionSync::WAIT_FOR_RESULT))
9393 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9394 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9395 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
9396 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
9397
9398 // Start drag on first window
9399 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
9400
9401 // Trigger cancel
9402 mDispatcher->cancelCurrentTouch();
9403 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
9404 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
9405 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
9406
9407 ASSERT_TRUE(mDispatcher->waitForIdle());
9408 // The D&D finished with nullptr
9409 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
9410
9411 // Remove drag window
9412 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
9413
9414 // Inject a simple gesture, ensure dispatcher not crashed
9415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9416 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9417 PointF{50, 50}))
9418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9419 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9420
9421 const MotionEvent moveEvent =
9422 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9423 .displayId(ADISPLAY_ID_DEFAULT)
9424 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9425 .build();
9426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9427 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
9428 InputEventInjectionSync::WAIT_FOR_RESULT))
9429 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9430 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
9431
9432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9433 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9434 {50, 50}))
9435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9436 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
9437}
9438
Vishnu Nair062a8672021-09-03 16:07:44 -07009439class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9440
9441TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9442 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009443 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9444 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009445 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009446 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9447 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009448 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009449 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009450 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009451
9452 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009453 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009454 window->assertNoEvents();
9455
Prabir Pradhan678438e2023-04-13 19:32:51 +00009456 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9457 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009458 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9459 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009460 window->assertNoEvents();
9461
9462 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009463 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009464 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009465
Prabir Pradhan678438e2023-04-13 19:32:51 +00009466 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009467 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9468
Prabir Pradhan678438e2023-04-13 19:32:51 +00009469 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9470 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009471 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9472 window->assertNoEvents();
9473}
9474
9475TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9476 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9477 std::make_shared<FakeApplicationHandle>();
9478 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009479 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9480 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009481 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009482 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009483 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9486 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009487 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009488 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009489 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9490 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009491 mDispatcher->onWindowInfosChanged(
9492 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009493 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009494 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009495
9496 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009497 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009498 window->assertNoEvents();
9499
Prabir Pradhan678438e2023-04-13 19:32:51 +00009500 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9501 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009502 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9503 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009504 window->assertNoEvents();
9505
9506 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009507 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009508 mDispatcher->onWindowInfosChanged(
9509 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009510
Prabir Pradhan678438e2023-04-13 19:32:51 +00009511 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009512 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9513
Prabir Pradhan678438e2023-04-13 19:32:51 +00009514 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9515 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009516 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9517 window->assertNoEvents();
9518}
9519
9520TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9521 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9522 std::make_shared<FakeApplicationHandle>();
9523 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009524 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9525 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009526 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009527 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009528 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009530 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9531 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009532 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009533 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009534 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9535 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009536 mDispatcher->onWindowInfosChanged(
9537 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009538 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009539 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009540
9541 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009542 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009543 window->assertNoEvents();
9544
Prabir Pradhan678438e2023-04-13 19:32:51 +00009545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009547 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9548 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009549 window->assertNoEvents();
9550
9551 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009552 mDispatcher->onWindowInfosChanged(
9553 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009554
Prabir Pradhan678438e2023-04-13 19:32:51 +00009555 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009556 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9557
Prabir Pradhan678438e2023-04-13 19:32:51 +00009558 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9559 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009560 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9561 window->assertNoEvents();
9562}
9563
Antonio Kantekf16f2832021-09-28 04:39:20 +00009564class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9565protected:
9566 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009567 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009568 sp<FakeWindowHandle> mWindow;
9569 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009570 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009571
9572 void SetUp() override {
9573 InputDispatcherTest::SetUp();
9574
9575 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009576 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009577 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009578 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009579 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009580 mSecondWindow =
9581 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009582 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009583 mThirdWindow =
9584 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9585 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9586 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009587
9588 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009589 mDispatcher->onWindowInfosChanged(
9590 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9591 {},
9592 0,
9593 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009594 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009595 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009596
Antonio Kantek15beb512022-06-13 22:35:41 +00009597 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009598 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009599 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009600 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9601 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009602 mThirdWindow->assertNoEvents();
9603 }
9604
9605 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9606 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009607 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009608 SECOND_DISPLAY_ID)) {
9609 mWindow->assertNoEvents();
9610 mSecondWindow->assertNoEvents();
9611 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009612 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009613 }
9614
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009615 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009616 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009617 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9618 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009619 mWindow->consumeTouchModeEvent(inTouchMode);
9620 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009621 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009622 }
9623};
9624
Antonio Kantek26defcf2022-02-08 01:12:27 +00009625TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009626 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009627 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9628 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009629 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009630}
9631
Antonio Kantek26defcf2022-02-08 01:12:27 +00009632TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9633 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009634 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009635 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009636 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009637 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009638 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009639 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009640 mWindow->assertNoEvents();
9641 mSecondWindow->assertNoEvents();
9642}
9643
9644TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9645 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009646 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009647 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009648 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009649 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009650 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009651}
9652
Antonio Kantekf16f2832021-09-28 04:39:20 +00009653TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009654 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009655 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9656 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009657 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009658 mWindow->assertNoEvents();
9659 mSecondWindow->assertNoEvents();
9660}
9661
Antonio Kantek15beb512022-06-13 22:35:41 +00009662TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9663 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9664 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9665 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009666 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009667 mWindow->assertNoEvents();
9668 mSecondWindow->assertNoEvents();
9669 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9670}
9671
Antonio Kantek48710e42022-03-24 14:19:30 -07009672TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9673 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9675 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009676 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9677 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9678
9679 // Then remove focus.
9680 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009681 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009682
9683 // Assert that caller can switch touch mode by owning one of the last interacted window.
9684 const WindowInfo& windowInfo = *mWindow->getInfo();
9685 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9686 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009687 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009688}
9689
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009690class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9691public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009692 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009693 std::shared_ptr<FakeApplicationHandle> application =
9694 std::make_shared<FakeApplicationHandle>();
9695 std::string name = "Fake Spy ";
9696 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009697 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9698 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009699 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009700 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009701 return spy;
9702 }
9703
9704 sp<FakeWindowHandle> createForeground() {
9705 std::shared_ptr<FakeApplicationHandle> application =
9706 std::make_shared<FakeApplicationHandle>();
9707 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009708 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9709 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009710 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009711 return window;
9712 }
9713
9714private:
9715 int mSpyCount{0};
9716};
9717
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009718using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009719/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009720 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9721 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009722TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009723 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009724 ScopedSilentDeath _silentDeath;
9725
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009726 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009727 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009728 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009729 ".* not a trusted overlay");
9730}
9731
9732/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009733 * Input injection into a display with a spy window but no foreground windows should succeed.
9734 */
9735TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009736 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009737 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009738
9739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009740 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9742 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9743}
9744
9745/**
9746 * Verify the order in which different input windows receive events. The touched foreground window
9747 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9748 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9749 * receive events before ones belows it.
9750 *
9751 * Here, we set up a scenario with four windows in the following Z order from the top:
9752 * spy1, spy2, window, spy3.
9753 * We then inject an event and verify that the foreground "window" receives it first, followed by
9754 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9755 * window.
9756 */
9757TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9758 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009759 auto spy1 = createSpy();
9760 auto spy2 = createSpy();
9761 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009762 mDispatcher->onWindowInfosChanged(
9763 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009764 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9765 const size_t numChannels = channels.size();
9766
Michael Wright8e9a8562022-02-09 13:44:29 +00009767 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009768 if (!epollFd.ok()) {
9769 FAIL() << "Failed to create epoll fd";
9770 }
9771
9772 for (size_t i = 0; i < numChannels; i++) {
9773 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9774 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9775 FAIL() << "Failed to add fd to epoll";
9776 }
9777 }
9778
9779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9782
9783 std::vector<size_t> eventOrder;
9784 std::vector<struct epoll_event> events(numChannels);
9785 for (;;) {
9786 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9787 (100ms).count());
9788 if (nFds < 0) {
9789 FAIL() << "Failed to call epoll_wait";
9790 }
9791 if (nFds == 0) {
9792 break; // epoll_wait timed out
9793 }
9794 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009795 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009796 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009797 channels[i]->consumeMotionDown();
9798 }
9799 }
9800
9801 // Verify the order in which the events were received.
9802 EXPECT_EQ(3u, eventOrder.size());
9803 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9804 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9805 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9806}
9807
9808/**
9809 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9810 */
9811TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9812 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009813 auto spy = createSpy();
9814 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009815 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009816
9817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009818 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9820 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9821 spy->assertNoEvents();
9822}
9823
9824/**
9825 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9826 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9827 * to the window.
9828 */
9829TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9830 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009831 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009832 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009833 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009834
9835 // Inject an event outside the spy window's touchable region.
9836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9839 window->consumeMotionDown();
9840 spy->assertNoEvents();
9841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009842 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9844 window->consumeMotionUp();
9845 spy->assertNoEvents();
9846
9847 // Inject an event inside the spy window's touchable region.
9848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009849 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009850 {5, 10}))
9851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9852 window->consumeMotionDown();
9853 spy->consumeMotionDown();
9854}
9855
9856/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009857 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009858 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009859 */
9860TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9861 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009862 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009863 auto spy = createSpy();
9864 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009865 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009866 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009867 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009868
9869 // Inject an event outside the spy window's frame and touchable region.
9870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009871 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009872 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009873 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9874 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009875 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009876}
9877
9878/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009879 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9880 * pointers that are down within its bounds.
9881 */
9882TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9883 auto windowLeft = createForeground();
9884 windowLeft->setFrame({0, 0, 100, 200});
9885 auto windowRight = createForeground();
9886 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009887 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009888 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009889 mDispatcher->onWindowInfosChanged(
9890 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009891
9892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009894 {50, 50}))
9895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9896 windowLeft->consumeMotionDown();
9897 spy->consumeMotionDown();
9898
9899 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009900 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009901 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009902 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9903 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009904 .build();
9905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009906 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009907 InputEventInjectionSync::WAIT_FOR_RESULT))
9908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9909 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009910 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009911}
9912
9913/**
9914 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9915 * the spy should receive the second pointer with ACTION_DOWN.
9916 */
9917TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9918 auto window = createForeground();
9919 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009920 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009921 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009922 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009923
9924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009925 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009926 {50, 50}))
9927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9928 window->consumeMotionDown();
9929 spyRight->assertNoEvents();
9930
9931 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009932 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009933 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009934 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9935 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009936 .build();
9937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009938 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009939 InputEventInjectionSync::WAIT_FOR_RESULT))
9940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009941 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009942 spyRight->consumeMotionDown();
9943}
9944
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009945/**
9946 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9947 * windows should be allowed to control split touch.
9948 */
9949TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009950 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009951 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009952 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009953 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009954
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009955 auto window = createForeground();
9956 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009957
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009958 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009959
9960 // First finger down, no window touched.
9961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009962 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009963 {100, 200}))
9964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9965 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9966 window->assertNoEvents();
9967
9968 // Second finger down on window, the window should receive touch down.
9969 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009970 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009971 .displayId(ADISPLAY_ID_DEFAULT)
9972 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009973 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9974 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009975 .build();
9976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009977 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009978 InputEventInjectionSync::WAIT_FOR_RESULT))
9979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9980
9981 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009982 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009983}
9984
9985/**
9986 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9987 * do not receive key events.
9988 */
9989TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009990 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009991 spy->setFocusable(false);
9992
9993 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009994 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009995 setFocusedWindow(window);
9996 window->consumeFocusEvent(true);
9997
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009999 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10000 window->consumeKeyDown(ADISPLAY_ID_NONE);
10001
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010003 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10004 window->consumeKeyUp(ADISPLAY_ID_NONE);
10005
10006 spy->assertNoEvents();
10007}
10008
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010009using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10010
10011/**
10012 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10013 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10014 */
10015TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10016 auto window = createForeground();
10017 auto spy1 = createSpy();
10018 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010019 mDispatcher->onWindowInfosChanged(
10020 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010021
10022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010023 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010024 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10025 window->consumeMotionDown();
10026 spy1->consumeMotionDown();
10027 spy2->consumeMotionDown();
10028
10029 // Pilfer pointers from the second spy window.
10030 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10031 spy2->assertNoEvents();
10032 spy1->consumeMotionCancel();
10033 window->consumeMotionCancel();
10034
10035 // The rest of the gesture should only be sent to the second spy window.
10036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010037 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010038 ADISPLAY_ID_DEFAULT))
10039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10040 spy2->consumeMotionMove();
10041 spy1->assertNoEvents();
10042 window->assertNoEvents();
10043}
10044
10045/**
10046 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10047 * in the middle of the gesture.
10048 */
10049TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10050 auto window = createForeground();
10051 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010052 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010053
10054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10057 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10058 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10059
10060 window->releaseChannel();
10061
10062 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10063
10064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010065 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010066 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10067 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10068}
10069
10070/**
10071 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10072 * the spy, but not to any other windows.
10073 */
10074TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10075 auto spy = createSpy();
10076 auto window = createForeground();
10077
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010078 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010079
10080 // First finger down on the window and the spy.
10081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010082 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010083 {100, 200}))
10084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10085 spy->consumeMotionDown();
10086 window->consumeMotionDown();
10087
10088 // Spy window pilfers the pointers.
10089 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10090 window->consumeMotionCancel();
10091
10092 // Second finger down on the window and spy, but the window should not receive the pointer down.
10093 const MotionEvent secondFingerDownEvent =
10094 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10095 .displayId(ADISPLAY_ID_DEFAULT)
10096 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010097 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10098 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010099 .build();
10100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010101 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010102 InputEventInjectionSync::WAIT_FOR_RESULT))
10103 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10104
Harry Cutts33476232023-01-30 19:57:29 +000010105 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010106
10107 // Third finger goes down outside all windows, so injection should fail.
10108 const MotionEvent thirdFingerDownEvent =
10109 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10110 .displayId(ADISPLAY_ID_DEFAULT)
10111 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010112 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10113 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10114 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010115 .build();
10116 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010117 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010118 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010119 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010120
10121 spy->assertNoEvents();
10122 window->assertNoEvents();
10123}
10124
10125/**
10126 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10127 */
10128TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10129 auto spy = createSpy();
10130 spy->setFrame(Rect(0, 0, 100, 100));
10131 auto window = createForeground();
10132 window->setFrame(Rect(0, 0, 200, 200));
10133
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010134 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010135
10136 // First finger down on the window only
10137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010138 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010139 {150, 150}))
10140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10141 window->consumeMotionDown();
10142
10143 // Second finger down on the spy and window
10144 const MotionEvent secondFingerDownEvent =
10145 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10146 .displayId(ADISPLAY_ID_DEFAULT)
10147 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010148 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10149 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010150 .build();
10151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010152 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010153 InputEventInjectionSync::WAIT_FOR_RESULT))
10154 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10155 spy->consumeMotionDown();
10156 window->consumeMotionPointerDown(1);
10157
10158 // Third finger down on the spy and window
10159 const MotionEvent thirdFingerDownEvent =
10160 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10161 .displayId(ADISPLAY_ID_DEFAULT)
10162 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010163 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10164 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10165 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010166 .build();
10167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010168 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010169 InputEventInjectionSync::WAIT_FOR_RESULT))
10170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10171 spy->consumeMotionPointerDown(1);
10172 window->consumeMotionPointerDown(2);
10173
10174 // Spy window pilfers the pointers.
10175 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010176 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10177 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010178
10179 spy->assertNoEvents();
10180 window->assertNoEvents();
10181}
10182
10183/**
10184 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10185 * other windows should be canceled. If this results in the cancellation of all pointers for some
10186 * window, then that window should receive ACTION_CANCEL.
10187 */
10188TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10189 auto spy = createSpy();
10190 spy->setFrame(Rect(0, 0, 100, 100));
10191 auto window = createForeground();
10192 window->setFrame(Rect(0, 0, 200, 200));
10193
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010194 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010195
10196 // First finger down on both spy and window
10197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010198 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010199 {10, 10}))
10200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10201 window->consumeMotionDown();
10202 spy->consumeMotionDown();
10203
10204 // Second finger down on the spy and window
10205 const MotionEvent secondFingerDownEvent =
10206 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10207 .displayId(ADISPLAY_ID_DEFAULT)
10208 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010209 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10210 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010211 .build();
10212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010213 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010214 InputEventInjectionSync::WAIT_FOR_RESULT))
10215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10216 spy->consumeMotionPointerDown(1);
10217 window->consumeMotionPointerDown(1);
10218
10219 // Spy window pilfers the pointers.
10220 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10221 window->consumeMotionCancel();
10222
10223 spy->assertNoEvents();
10224 window->assertNoEvents();
10225}
10226
10227/**
10228 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10229 * be sent to other windows
10230 */
10231TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10232 auto spy = createSpy();
10233 spy->setFrame(Rect(0, 0, 100, 100));
10234 auto window = createForeground();
10235 window->setFrame(Rect(0, 0, 200, 200));
10236
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010237 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010238
10239 // First finger down on both window and spy
10240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010241 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010242 {10, 10}))
10243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10244 window->consumeMotionDown();
10245 spy->consumeMotionDown();
10246
10247 // Spy window pilfers the pointers.
10248 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10249 window->consumeMotionCancel();
10250
10251 // Second finger down on the window only
10252 const MotionEvent secondFingerDownEvent =
10253 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10254 .displayId(ADISPLAY_ID_DEFAULT)
10255 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010256 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10257 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010258 .build();
10259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010260 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010261 InputEventInjectionSync::WAIT_FOR_RESULT))
10262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10263 window->consumeMotionDown();
10264 window->assertNoEvents();
10265
10266 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10267 spy->consumeMotionMove();
10268 spy->assertNoEvents();
10269}
10270
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010271/**
10272 * A window on the left and a window on the right. Also, a spy window that's above all of the
10273 * windows, and spanning both left and right windows.
10274 * Send simultaneous motion streams from two different devices, one to the left window, and another
10275 * to the right window.
10276 * Pilfer from spy window.
10277 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10278 */
10279TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10280 sp<FakeWindowHandle> spy = createSpy();
10281 spy->setFrame(Rect(0, 0, 200, 200));
10282 sp<FakeWindowHandle> leftWindow = createForeground();
10283 leftWindow->setFrame(Rect(0, 0, 100, 100));
10284
10285 sp<FakeWindowHandle> rightWindow = createForeground();
10286 rightWindow->setFrame(Rect(100, 0, 200, 100));
10287
10288 constexpr int32_t stylusDeviceId = 1;
10289 constexpr int32_t touchDeviceId = 2;
10290
10291 mDispatcher->onWindowInfosChanged(
10292 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10293
10294 // Stylus down on left window and spy
10295 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10296 .deviceId(stylusDeviceId)
10297 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10298 .build());
10299 leftWindow->consumeMotionEvent(
10300 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10301 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10302
10303 // Finger down on right window and spy - but spy already has stylus
10304 mDispatcher->notifyMotion(
10305 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10306 .deviceId(touchDeviceId)
10307 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10308 .build());
10309 rightWindow->consumeMotionEvent(
10310 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10311 leftWindow->consumeMotionEvent(
10312 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10313 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10314 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10315
10316 // Act: pilfer from spy. Spy is currently receiving touch events.
10317 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10318 rightWindow->consumeMotionEvent(
10319 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10320
10321 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10322 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10323 .deviceId(stylusDeviceId)
10324 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10325 .build());
10326 mDispatcher->notifyMotion(
10327 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10328 .deviceId(touchDeviceId)
10329 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10330 .build());
10331 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10332
10333 spy->assertNoEvents();
10334 leftWindow->assertNoEvents();
10335 rightWindow->assertNoEvents();
10336}
10337
Prabir Pradhand65552b2021-10-07 11:23:50 -070010338class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10339public:
10340 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10341 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10342 std::make_shared<FakeApplicationHandle>();
10343 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010344 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10345 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010346 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010347 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010348 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010349 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010350 overlay->setTrustedOverlay(true);
10351
10352 std::shared_ptr<FakeApplicationHandle> application =
10353 std::make_shared<FakeApplicationHandle>();
10354 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010355 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10356 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010357 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010358 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010359
10360 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010361 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010362 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010363 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010364 return {std::move(overlay), std::move(window)};
10365 }
10366
10367 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010368 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010369 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010370 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010371 }
10372
10373 void sendStylusEvent(int32_t action) {
10374 NotifyMotionArgs motionArgs =
10375 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10376 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010377 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010378 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010379 }
10380};
10381
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010382using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10383
10384TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010385 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010386 ScopedSilentDeath _silentDeath;
10387
Prabir Pradhand65552b2021-10-07 11:23:50 -070010388 auto [overlay, window] = setupStylusOverlayScenario();
10389 overlay->setTrustedOverlay(false);
10390 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010391 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10392 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010393 ".* not a trusted overlay");
10394}
10395
10396TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10397 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010398 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010399
10400 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10401 overlay->consumeMotionDown();
10402 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10403 overlay->consumeMotionUp();
10404
10405 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10406 window->consumeMotionDown();
10407 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10408 window->consumeMotionUp();
10409
10410 overlay->assertNoEvents();
10411 window->assertNoEvents();
10412}
10413
10414TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10415 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010416 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010417 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010418
10419 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10420 overlay->consumeMotionDown();
10421 window->consumeMotionDown();
10422 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10423 overlay->consumeMotionUp();
10424 window->consumeMotionUp();
10425
10426 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10427 window->consumeMotionDown();
10428 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10429 window->consumeMotionUp();
10430
10431 overlay->assertNoEvents();
10432 window->assertNoEvents();
10433}
10434
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010435/**
10436 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10437 * The scenario is as follows:
10438 * - The stylus interceptor overlay is configured as a spy window.
10439 * - The stylus interceptor spy receives the start of a new stylus gesture.
10440 * - It pilfers pointers and then configures itself to no longer be a spy.
10441 * - The stylus interceptor continues to receive the rest of the gesture.
10442 */
10443TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10444 auto [overlay, window] = setupStylusOverlayScenario();
10445 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010446 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010447
10448 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10449 overlay->consumeMotionDown();
10450 window->consumeMotionDown();
10451
10452 // The interceptor pilfers the pointers.
10453 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10454 window->consumeMotionCancel();
10455
10456 // The interceptor configures itself so that it is no longer a spy.
10457 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010458 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010459
10460 // It continues to receive the rest of the stylus gesture.
10461 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10462 overlay->consumeMotionMove();
10463 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10464 overlay->consumeMotionUp();
10465
10466 window->assertNoEvents();
10467}
10468
Prabir Pradhan5735a322022-04-11 17:23:34 +000010469struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010470 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010471 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010472 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10473 std::unique_ptr<InputDispatcher>& mDispatcher;
10474
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010475 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010476 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10477
10478 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010479 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010480 ADISPLAY_ID_DEFAULT, {100, 200},
10481 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10482 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10483 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10484 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10485 }
10486
10487 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010488 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010489 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010490 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010491 mPolicyFlags);
10492 }
10493
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010494 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010495 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10496 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010497 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10498 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010499 window->setOwnerInfo(mPid, mUid);
10500 return window;
10501 }
10502};
10503
10504using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10505
10506TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010507 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010508 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010509 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010510
10511 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10512 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10513 window->consumeMotionDown();
10514
10515 setFocusedWindow(window);
10516 window->consumeFocusEvent(true);
10517
10518 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10519 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10520 window->consumeKeyDown(ADISPLAY_ID_NONE);
10521}
10522
10523TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010524 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010525 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010526 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010527
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010528 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010529 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10530 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10531
10532 setFocusedWindow(window);
10533 window->consumeFocusEvent(true);
10534
10535 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10536 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10537 window->assertNoEvents();
10538}
10539
10540TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010541 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010542 auto window = owner.createWindow("Owned window");
10543 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010544 spy->setSpy(true);
10545 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010546 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010547
10548 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10549 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10550 spy->consumeMotionDown();
10551 window->consumeMotionDown();
10552}
10553
10554TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010555 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010556 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010557
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010558 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010559 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010560 randosSpy->setSpy(true);
10561 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010562 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010563
10564 // The event is targeted at owner's window, so injection should succeed, but the spy should
10565 // not receive the event.
10566 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10567 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10568 randosSpy->assertNoEvents();
10569 window->consumeMotionDown();
10570}
10571
10572TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010573 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010574 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010575
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010576 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010577 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010578 randosSpy->setSpy(true);
10579 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010580 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010581
10582 // A user that has injection permission can inject into any window.
10583 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010584 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010585 ADISPLAY_ID_DEFAULT));
10586 randosSpy->consumeMotionDown();
10587 window->consumeMotionDown();
10588
10589 setFocusedWindow(randosSpy);
10590 randosSpy->consumeFocusEvent(true);
10591
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010592 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010593 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10594 window->assertNoEvents();
10595}
10596
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010597TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010598 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010599 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010600
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010601 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010602 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010603 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10604 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010605 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010606
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010607 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010608 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10609 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10610 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010611 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010612}
10613
Garfield Tane84e6f92019-08-29 17:28:41 -070010614} // namespace android::inputdispatcher