blob: f0602dfbad9f4d0dc38c1dba444576ef2b080c79 [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 Vishniakou487c49b2022-12-02 15:48:57 -080076static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080077static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080078/**
79 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
80 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
81 * index 0) is the new pointer going down. The same pointer could have been placed at a different
82 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
83 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
84 * pointer id=0 leaves but the pointer id=1 remains.
85 */
86static constexpr int32_t POINTER_0_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080088static constexpr int32_t POINTER_1_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000090static constexpr int32_t POINTER_2_DOWN =
91 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000092static constexpr int32_t POINTER_3_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000094static constexpr int32_t POINTER_0_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096static constexpr int32_t POINTER_1_UP =
97 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000098static constexpr int32_t POINTER_2_UP =
99 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100
Antonio Kantek15beb512022-06-13 22:35:41 +0000101// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000102static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000103static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000104
Antonio Kantek15beb512022-06-13 22:35:41 +0000105// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000106static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000107static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000108
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000109// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000110static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000111
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800112static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
113
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700114/**
115 * If we expect to receive the event, the timeout can be made very long. When the test are running
116 * correctly, we will actually never wait until the end of the timeout because the wait will end
117 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
118 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
119 * developer can see the failure quickly (on human scale).
120 */
121static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
122/**
123 * When no event is expected, we can have a very short timeout. A large value here would slow down
124 * the tests. In the unlikely event of system being too slow, the event may still be present but the
125 * timeout would complete before it is consumed. This would result in test flakiness. If this
126 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
127 * would get noticed and addressed quickly.
128 */
129static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
130
Arthur Hungc539dbb2022-12-08 07:45:36 +0000131static constexpr int expectedWallpaperFlags =
132 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
133
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800134using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
135
chaviwd1c23182019-12-20 18:44:56 -0800136struct PointF {
137 float x;
138 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800139 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800140};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800141
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700142inline std::string pointFToString(const PointF& p) {
143 return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
144}
145
Gang Wang342c9272020-01-13 13:15:04 -0500146/**
147 * Return a DOWN key event with KEYCODE_A.
148 */
149static KeyEvent getTestKeyEvent() {
150 KeyEvent event;
151
Garfield Tanfbe732e2020-01-24 11:26:14 -0800152 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
153 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
154 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500155 return event;
156}
157
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800158MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700159 *result_listener << "expected downTime " << downTime << ", but got " << arg.getDownTime();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800160 return arg.getDownTime() == downTime;
161}
162
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800163MATCHER_P(WithSource, source, "InputEvent with specified source") {
164 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
165 << inputEventSourceToString(arg.getSource());
166 return arg.getSource() == source;
167}
168
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800169MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700170 *result_listener << "expected flags " << std::hex << flags << ", but got " << arg.getFlags();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800171 return arg.getFlags() == flags;
172}
173
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800174MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
175 if (arg.getPointerCount() != 1) {
176 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
177 return false;
178 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700179 const float receivedX = arg.getX(/*pointerIndex=*/0);
180 const float receivedY = arg.getY(/*pointerIndex=*/0);
181 *result_listener << "expected coords (" << x << ", " << y << "), but got (" << receivedX << ", "
182 << receivedY << ")";
183 return receivedX == x && receivedY == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800184}
185
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800186MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700187 *result_listener << "expected pointerCount " << pointerCount << ", but got "
188 << arg.getPointerCount();
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800189 return arg.getPointerCount() == pointerCount;
190}
191
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800192MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
193 // Build a map for the received pointers, by pointer id
194 std::map<int32_t /*pointerId*/, PointF> actualPointers;
195 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
196 const int32_t pointerId = arg.getPointerId(pointerIndex);
197 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
198 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700199 *result_listener << "expected pointers " << dumpMap(pointers, constToString, pointFToString)
200 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800201 return pointers == actualPointers;
202}
203
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204// --- FakeInputDispatcherPolicy ---
205
206class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000207 struct AnrResult {
208 sp<IBinder> token{};
209 gui::Pid pid{gui::Pid::INVALID};
210 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800211
Michael Wrightd02c5b62014-02-10 15:10:22 -0800212public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000213 FakeInputDispatcherPolicy() = default;
214 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800215
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800216 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700217 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700218 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700219 EXPECT_EQ(event.getDisplayId(), args.displayId);
220
221 const auto& keyEvent = static_cast<const KeyEvent&>(event);
222 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
223 EXPECT_EQ(keyEvent.getAction(), args.action);
224 });
Jackal Guof9696682018-10-05 12:23:23 +0800225 }
226
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700227 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
228 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700229 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700230 EXPECT_EQ(event.getDisplayId(), args.displayId);
231
232 const auto& motionEvent = static_cast<const MotionEvent&>(event);
233 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
234 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000235 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
236 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
237 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700239 });
Jackal Guof9696682018-10-05 12:23:23 +0800240 }
241
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700242 void assertFilterInputEventWasNotCalled() {
243 std::scoped_lock lock(mLock);
244 ASSERT_EQ(nullptr, mFilteredEvent);
245 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800246
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800247 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700248 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800249 ASSERT_TRUE(mConfigurationChangedTime)
250 << "Timed out waiting for configuration changed call";
251 ASSERT_EQ(*mConfigurationChangedTime, when);
252 mConfigurationChangedTime = std::nullopt;
253 }
254
255 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700256 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800257 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800258 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800259 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
260 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
261 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
262 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
263 mLastNotifySwitch = std::nullopt;
264 }
265
chaviwfd6d3512019-03-25 13:23:49 -0700266 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700267 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800268 ASSERT_EQ(touchedToken, mOnPointerDownToken);
269 mOnPointerDownToken.clear();
270 }
271
272 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700273 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800274 ASSERT_TRUE(mOnPointerDownToken == nullptr)
275 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700276 }
277
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700278 // This function must be called soon after the expected ANR timer starts,
279 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500280 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700281 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500282 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800283 std::unique_lock lock(mLock);
284 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500285 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800286 ASSERT_NO_FATAL_FAILURE(
287 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500288 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700289 }
290
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000291 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800292 const sp<WindowInfoHandle>& window) {
293 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
294 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
295 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500296 }
297
Prabir Pradhanedd96402022-02-15 01:46:16 -0800298 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
299 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000300 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800301 std::unique_lock lock(mLock);
302 android::base::ScopedLockAssertion assumeLocked(mLock);
303 AnrResult result;
304 ASSERT_NO_FATAL_FAILURE(result =
305 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000306 ASSERT_EQ(expectedToken, result.token);
307 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500308 }
309
Prabir Pradhanedd96402022-02-15 01:46:16 -0800310 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000311 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500312 std::unique_lock lock(mLock);
313 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800314 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
315 const auto& [token, _] = result;
316 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000317 }
318
Prabir Pradhanedd96402022-02-15 01:46:16 -0800319 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000320 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800321 std::unique_lock lock(mLock);
322 android::base::ScopedLockAssertion assumeLocked(mLock);
323 AnrResult result;
324 ASSERT_NO_FATAL_FAILURE(
325 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000326 ASSERT_EQ(expectedToken, result.token);
327 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800328 }
329
330 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000331 sp<IBinder> getResponsiveWindowToken() {
332 std::unique_lock lock(mLock);
333 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800334 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
335 const auto& [token, _] = result;
336 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700337 }
338
339 void assertNotifyAnrWasNotCalled() {
340 std::scoped_lock lock(mLock);
341 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800342 ASSERT_TRUE(mAnrWindows.empty());
343 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500344 << "ANR was not called, but please also consume the 'connection is responsive' "
345 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700346 }
347
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000348 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800349 std::unique_lock lock(mLock);
350 base::ScopedLockAssertion assumeLocked(mLock);
351
352 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
353 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000354 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800355 enabled;
356 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000357 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
358 << ") to be called.";
359 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800360 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000361 auto request = *mPointerCaptureRequest;
362 mPointerCaptureRequest.reset();
363 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800364 }
365
366 void assertSetPointerCaptureNotCalled() {
367 std::unique_lock lock(mLock);
368 base::ScopedLockAssertion assumeLocked(mLock);
369
370 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000371 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800372 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000373 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800374 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000375 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800376 }
377
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700378 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
379 const sp<IBinder>& targetToken) {
380 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800381 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800382 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800383 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800384 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800385 }
386
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800387 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<sp<IBinder>> receivedToken =
391 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
392 mNotifyInputChannelBroken);
393 ASSERT_TRUE(receivedToken.has_value());
394 ASSERT_EQ(token, *receivedToken);
395 }
396
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800397 /**
398 * Set policy timeout. A value of zero means next key will not be intercepted.
399 */
400 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
401 mInterceptKeyTimeout = timeout;
402 }
403
Josep del Riob3981622023-04-18 15:49:45 +0000404 void assertUserActivityPoked() {
405 std::scoped_lock lock(mLock);
406 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
407 }
408
409 void assertUserActivityNotPoked() {
410 std::scoped_lock lock(mLock);
411 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
412 }
413
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000414 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000415 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
416 }
417
418 void assertNotifyDeviceInteractionWasNotCalled() {
419 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
420 }
421
Michael Wrightd02c5b62014-02-10 15:10:22 -0800422private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700423 std::mutex mLock;
424 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
425 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
426 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
427 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800428
Prabir Pradhan99987712020-11-10 18:43:05 -0800429 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000430
431 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800432
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700433 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700434 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800435 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
436 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700437 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800438 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
439 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700440
arthurhungf452d0b2021-01-06 00:19:52 +0800441 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800442 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000443 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800444
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800445 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
446
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000447 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000448
Prabir Pradhanedd96402022-02-15 01:46:16 -0800449 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
450 // for a specific container to become non-empty. When the container is non-empty, return the
451 // first entry from the container and erase it.
452 template <class T>
453 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
454 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
455 // If there is an ANR, Dispatcher won't be idle because there are still events
456 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
457 // before checking if ANR was called.
458 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
459 // to provide it some time to act. 100ms seems reasonable.
460 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
461 const std::chrono::time_point start = std::chrono::steady_clock::now();
462 std::optional<T> token =
463 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
464 if (!token.has_value()) {
465 ADD_FAILURE() << "Did not receive the ANR callback";
466 return {};
467 }
468
469 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
470 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
471 // the dispatcher started counting before this function was called
472 if (std::chrono::abs(timeout - waited) > 100ms) {
473 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
474 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
475 << "ms, but waited "
476 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
477 << "ms instead";
478 }
479 return *token;
480 }
481
482 template <class T>
483 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
484 std::queue<T>& storage,
485 std::unique_lock<std::mutex>& lock,
486 std::condition_variable& condition)
487 REQUIRES(mLock) {
488 condition.wait_for(lock, timeout,
489 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
490 if (storage.empty()) {
491 ADD_FAILURE() << "Did not receive the expected callback";
492 return std::nullopt;
493 }
494 T item = storage.front();
495 storage.pop();
496 return std::make_optional(item);
497 }
498
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600499 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700500 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800501 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800502 }
503
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000504 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800505 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700506 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800507 ASSERT_TRUE(pid.has_value());
508 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700509 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500510 }
511
Prabir Pradhanedd96402022-02-15 01:46:16 -0800512 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000513 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500514 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800515 ASSERT_TRUE(pid.has_value());
516 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500517 mNotifyAnr.notify_all();
518 }
519
520 void notifyNoFocusedWindowAnr(
521 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
522 std::scoped_lock lock(mLock);
523 mAnrApplications.push(applicationHandle);
524 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525 }
526
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800527 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
528 std::scoped_lock lock(mLock);
529 mBrokenInputChannels.push(connectionToken);
530 mNotifyInputChannelBroken.notify_all();
531 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800532
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600533 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700534
Chris Yef59a2f42020-10-16 12:55:26 -0700535 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
536 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
537 const std::vector<float>& values) override {}
538
539 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
540 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000541
Chris Yefb552902021-02-03 17:18:37 -0800542 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
543
Prabir Pradhana41d2442023-04-20 21:30:40 +0000544 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700545 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000546 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700547 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000548 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
549 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800550 break;
551 }
552
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700553 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
555 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800556 break;
557 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700558 default: {
559 ADD_FAILURE() << "Should only filter keys or motions";
560 break;
561 }
Jackal Guof9696682018-10-05 12:23:23 +0800562 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 return true;
564 }
565
Prabir Pradhana41d2442023-04-20 21:30:40 +0000566 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
567 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800568 // Clear intercept state when we handled the event.
569 mInterceptKeyTimeout = 0ms;
570 }
571 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800572
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600573 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574
Prabir Pradhana41d2442023-04-20 21:30:40 +0000575 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800576 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
577 // Clear intercept state so we could dispatch the event in next wake.
578 mInterceptKeyTimeout = 0ms;
579 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580 }
581
Prabir Pradhana41d2442023-04-20 21:30:40 +0000582 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
583 uint32_t) override {
584 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585 }
586
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600587 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
588 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800590 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
591 * essentially a passthrough for notifySwitch.
592 */
Harry Cutts33476232023-01-30 19:57:29 +0000593 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594 }
595
Josep del Riob3981622023-04-18 15:49:45 +0000596 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
597 std::scoped_lock lock(mLock);
598 mPokedUserActivity = true;
599 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800600
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600601 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700602 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700603 mOnPointerDownToken = newToken;
604 }
605
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000606 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800607 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000608 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800609 mPointerCaptureChangedCondition.notify_all();
610 }
611
arthurhungf452d0b2021-01-06 00:19:52 +0800612 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
613 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800614 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800615 mDropTargetWindowToken = token;
616 }
617
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000618 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000619 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000620 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
621 }
622
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700623 void assertFilterInputEventWasCalledInternal(
624 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700625 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800626 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700627 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800628 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800629 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800630};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700631} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633// --- InputDispatcherTest ---
634
635class InputDispatcherTest : public testing::Test {
636protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000637 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700638 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800639
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000640 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000641 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
642 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000643 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000644 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700645 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800646 }
647
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000648 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700649 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000650 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700651 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700653
654 /**
655 * Used for debugging when writing the test
656 */
657 void dumpDispatcherState() {
658 std::string dump;
659 mDispatcher->dump(dump);
660 std::stringstream ss(dump);
661 std::string to;
662
663 while (std::getline(ss, to, '\n')) {
664 ALOGE("%s", to.c_str());
665 }
666 }
Vishnu Nair958da932020-08-21 17:12:37 -0700667
Chavi Weingarten847e8512023-03-29 00:26:09 +0000668 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700669 FocusRequest request;
670 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000671 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700672 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
673 request.displayId = window->getInfo()->displayId;
674 mDispatcher->setFocusedWindow(request);
675 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676};
677
Michael Wrightd02c5b62014-02-10 15:10:22 -0800678TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
679 KeyEvent event;
680
681 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800682 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
683 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000684 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600685 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800686 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000687 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000688 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800689 << "Should reject key events with undefined action.";
690
691 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800692 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
693 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600694 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800695 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000696 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000697 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800698 << "Should reject key events with ACTION_MULTIPLE.";
699}
700
701TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
702 MotionEvent event;
703 PointerProperties pointerProperties[MAX_POINTERS + 1];
704 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800705 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 pointerProperties[i].clear();
707 pointerProperties[i].id = i;
708 pointerCoords[i].clear();
709 }
710
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800711 // Some constants commonly used below
712 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
713 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
714 constexpr int32_t metaState = AMETA_NONE;
715 constexpr MotionClassification classification = MotionClassification::NONE;
716
chaviw9eaa22c2020-07-01 16:21:27 -0700717 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800718 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000720 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000724 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with undefined action.";
729
730 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800731 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800732 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
733 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
735 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000736 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too large.";
741
Garfield Tanfbe732e2020-01-24 11:26:14 -0800742 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700743 AMOTION_EVENT_ACTION_POINTER_DOWN |
744 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700745 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700747 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000748 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer down index too small.";
753
754 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800755 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800756 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
757 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
759 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000760 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too large.";
765
Garfield Tanfbe732e2020-01-24 11:26:14 -0800766 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700767 AMOTION_EVENT_ACTION_POINTER_UP |
768 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700769 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
770 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700771 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000772 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with pointer up index too small.";
777
778 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800779 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
780 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700781 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700782 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
783 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000784 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800785 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000786 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000787 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800788 << "Should reject motion events with 0 pointers.";
789
Garfield Tanfbe732e2020-01-24 11:26:14 -0800790 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
791 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700792 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700793 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
794 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000795 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800796 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000797 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000798 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800799 << "Should reject motion events with more than MAX_POINTERS pointers.";
800
801 // Rejects motion events with invalid pointer ids.
802 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with pointer ids less than 0.";
813
814 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800815 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
816 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700817 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700818 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
819 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000820 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800821 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000822 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000823 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800824 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
825
826 // Rejects motion events with duplicate pointer ids.
827 pointerProperties[0].id = 1;
828 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800829 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
830 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700831 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700832 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
833 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000834 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800835 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000836 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000837 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800838 << "Should reject motion events with duplicate pointer ids.";
839}
840
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800841/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
842
843TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
844 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000845 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800846 ASSERT_TRUE(mDispatcher->waitForIdle());
847
848 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
849}
850
851TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000852 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
853 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000854 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800855
856 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
857 args.policyFlags |= POLICY_FLAG_TRUSTED;
858 mFakePolicy->assertNotifySwitchWasCalled(args);
859}
860
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700861namespace {
862
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700863static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700864// Default input dispatching timeout if there is no focused application or paused window
865// from which to determine an appropriate dispatching timeout.
866static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
867 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
868 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800869
870class FakeApplicationHandle : public InputApplicationHandle {
871public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700872 FakeApplicationHandle() {
873 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700874 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500875 mInfo.dispatchingTimeoutMillis =
876 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700877 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800878 virtual ~FakeApplicationHandle() {}
879
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000880 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500882 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
883 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800885};
886
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800887class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800888public:
Garfield Tan15601662020-09-22 15:32:38 -0700889 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800890 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700891 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800892 }
893
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700894 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700895 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700896 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 if (!consumeSeq) {
898 return nullptr;
899 }
900 finishEvent(*consumeSeq);
901 return event;
902 }
903
904 /**
905 * Receive an event without acknowledging it.
906 * Return the sequence number that could later be used to send finished signal.
907 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700908 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
909 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800910 uint32_t consumeSeq;
911 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800912
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800913 std::chrono::time_point start = std::chrono::steady_clock::now();
914 status_t status = WOULD_BLOCK;
915 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000916 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800917 &event);
918 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700919 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 break;
921 }
922 }
923
924 if (status == WOULD_BLOCK) {
925 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700926 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800927 }
928
929 if (status != OK) {
930 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800932 }
933 if (event == nullptr) {
934 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700935 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800936 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700937 if (outEvent != nullptr) {
938 *outEvent = event;
939 }
940 return consumeSeq;
941 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800942
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700943 /**
944 * To be used together with "receiveEvent" to complete the consumption of an event.
945 */
946 void finishEvent(uint32_t consumeSeq) {
947 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
948 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800949 }
950
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000951 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
952 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
953 ASSERT_EQ(OK, status);
954 }
955
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700956 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000957 std::optional<int32_t> expectedDisplayId,
958 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700959 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800960
961 ASSERT_NE(nullptr, event) << mName.c_str()
962 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800963 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
965 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800966
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000967 if (expectedDisplayId.has_value()) {
968 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970
Tiger Huang8664f8c2018-10-11 19:14:35 +0800971 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800973 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700974 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000975 if (expectedFlags.has_value()) {
976 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
977 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800978 break;
979 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800981 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700982 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000983 if (expectedFlags.has_value()) {
984 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986 break;
987 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100989 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
990 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700991 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800992 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
993 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700994 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000995 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
996 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800998 FAIL() << "Use 'consumeDragEvent' for DRAG events";
999 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001000 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001001 }
1002
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001003 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001004 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001005
1006 if (event == nullptr) {
1007 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1008 return nullptr;
1009 }
1010
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001011 if (event->getType() != InputEventType::MOTION) {
1012 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001013 return nullptr;
1014 }
1015 return static_cast<MotionEvent*>(event);
1016 }
1017
1018 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1019 MotionEvent* motionEvent = consumeMotion();
1020 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1021 ASSERT_THAT(*motionEvent, matcher);
1022 }
1023
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001024 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001025 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001026 ASSERT_NE(nullptr, event) << mName.c_str()
1027 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001028 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1029 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001030
1031 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1032 << mName.c_str() << ": event displayId should always be NONE.";
1033
1034 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1035 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001036 }
1037
Prabir Pradhan99987712020-11-10 18:43:05 -08001038 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001039 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001040 ASSERT_NE(nullptr, event) << mName.c_str()
1041 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001042 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1043 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001044
1045 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1046 << mName.c_str() << ": event displayId should always be NONE.";
1047
1048 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1049 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1050 }
1051
arthurhungb89ccb02020-12-30 16:19:01 +08001052 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001053 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001054 ASSERT_NE(nullptr, event) << mName.c_str()
1055 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001056 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001057
1058 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1059 << mName.c_str() << ": event displayId should always be NONE.";
1060
1061 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1062 EXPECT_EQ(isExiting, dragEvent.isExiting());
1063 EXPECT_EQ(x, dragEvent.getX());
1064 EXPECT_EQ(y, dragEvent.getY());
1065 }
1066
Antonio Kantekf16f2832021-09-28 04:39:20 +00001067 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001068 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001069 ASSERT_NE(nullptr, event) << mName.c_str()
1070 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001071 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1072 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001073
1074 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1075 << mName.c_str() << ": event displayId should always be NONE.";
1076 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1077 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1078 }
1079
chaviwd1c23182019-12-20 18:44:56 -08001080 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001081 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001082 if (event == nullptr) {
1083 return;
1084 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001085 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001086 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1087 ADD_FAILURE() << "Received key event "
1088 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001089 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001090 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1091 ADD_FAILURE() << "Received motion event "
1092 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001093 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1095 ADD_FAILURE() << "Received focus event, hasFocus = "
1096 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001097 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001098 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1099 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1100 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001102 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1103 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1104 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001105 }
1106 FAIL() << mName.c_str()
1107 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001108 }
1109
1110 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1111
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001112 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1113
chaviwd1c23182019-12-20 18:44:56 -08001114protected:
1115 std::unique_ptr<InputConsumer> mConsumer;
1116 PreallocatedInputEventFactory mEventFactory;
1117
1118 std::string mName;
1119};
1120
chaviw3277faf2021-05-19 16:45:23 -05001121class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001122public:
1123 static const int32_t WIDTH = 600;
1124 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001125
Chris Yea209fde2020-07-22 13:54:51 -07001126 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001127 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001128 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001129 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001130 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001131 base::Result<std::unique_ptr<InputChannel>> channel =
1132 dispatcher->createInputChannel(name);
1133 token = (*channel)->getConnectionToken();
1134 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001135 }
1136
1137 inputApplicationHandle->updateInfo();
1138 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1139
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001140 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001141 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001142 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001143 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001144 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001145 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001146 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001147 mInfo.globalScaleFactor = 1.0;
1148 mInfo.touchableRegion.clear();
1149 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001150 mInfo.ownerPid = WINDOW_PID;
1151 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001152 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001153 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001154 }
1155
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001156 sp<FakeWindowHandle> clone(int32_t displayId) {
1157 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1158 handle->mInfo = mInfo;
1159 handle->mInfo.displayId = displayId;
1160 handle->mInfo.id = sId++;
1161 handle->mInputReceiver = mInputReceiver;
1162 return handle;
1163 }
1164
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001165 void setTouchable(bool touchable) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1167 }
chaviwd1c23182019-12-20 18:44:56 -08001168
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001169 void setFocusable(bool focusable) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1171 }
1172
1173 void setVisible(bool visible) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1175 }
Vishnu Nair958da932020-08-21 17:12:37 -07001176
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001177 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001178 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001179 }
1180
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001181 void setPaused(bool paused) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1183 }
1184
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001185 void setPreventSplitting(bool preventSplitting) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001187 }
1188
1189 void setSlippery(bool slippery) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1191 }
1192
1193 void setWatchOutsideTouch(bool watchOutside) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1195 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001196
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001197 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1198
1199 void setInterceptsStylus(bool interceptsStylus) {
1200 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1201 }
1202
1203 void setDropInput(bool dropInput) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1205 }
1206
1207 void setDropInputIfObscured(bool dropInputIfObscured) {
1208 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1209 }
1210
1211 void setNoInputChannel(bool noInputChannel) {
1212 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1213 }
1214
Josep del Riob3981622023-04-18 15:49:45 +00001215 void setDisableUserActivity(bool disableUserActivity) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1217 }
1218
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001219 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1220
chaviw3277faf2021-05-19 16:45:23 -05001221 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001222
Bernardo Rufino7393d172021-02-26 13:56:11 +00001223 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1224
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001225 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001226 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001227 mInfo.touchableRegion.clear();
1228 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001229
1230 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1231 ui::Transform translate;
1232 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1233 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001234 }
1235
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001236 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1237
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001238 void setIsWallpaper(bool isWallpaper) {
1239 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1240 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001241
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001242 void setDupTouchToWallpaper(bool hasWallpaper) {
1243 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1244 }
chaviwd1c23182019-12-20 18:44:56 -08001245
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001246 void setTrustedOverlay(bool trustedOverlay) {
1247 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1248 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001249
chaviw9eaa22c2020-07-01 16:21:27 -07001250 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1251 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1252 }
1253
1254 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001255
yunho.shinf4a80b82020-11-16 21:13:57 +09001256 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1257
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001258 KeyEvent* consumeKey() {
1259 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1260 if (event == nullptr) {
1261 ADD_FAILURE() << "Consume failed : no event";
1262 return nullptr;
1263 }
1264 if (event->getType() != InputEventType::KEY) {
1265 ADD_FAILURE() << "Instead of key event, got " << *event;
1266 return nullptr;
1267 }
1268 return static_cast<KeyEvent*>(event);
1269 }
1270
1271 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1272 KeyEvent* keyEvent = consumeKey();
1273 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1274 ASSERT_THAT(*keyEvent, matcher);
1275 }
1276
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001277 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001278 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001279 }
1280
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001281 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001282 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001283 }
1284
Svet Ganov5d3bc372020-01-26 23:11:07 -08001285 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001287 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1288 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 }
1290
1291 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001293 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1294 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001295 }
1296
1297 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001299 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1300 }
1301
1302 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1303 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001304 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001305 expectedFlags);
1306 }
1307
Svet Ganov5d3bc372020-01-26 23:11:07 -08001308 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001309 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1310 int32_t expectedFlags = 0) {
1311 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1312 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001313 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001314 }
1315
1316 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001317 int32_t expectedFlags = 0) {
1318 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1319 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001320 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001321 }
1322
1323 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001324 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001325 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001326 expectedFlags);
1327 }
1328
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001329 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1330 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001331 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001332 expectedFlags);
1333 }
1334
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001335 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1336 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001337 MotionEvent* motionEvent = consumeMotion();
1338 ASSERT_NE(nullptr, motionEvent);
1339 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1340 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1341 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001342 }
1343
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001344 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1345 ASSERT_NE(mInputReceiver, nullptr)
1346 << "Cannot consume events from a window with no receiver";
1347 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1348 }
1349
Prabir Pradhan99987712020-11-10 18:43:05 -08001350 void consumeCaptureEvent(bool hasCapture) {
1351 ASSERT_NE(mInputReceiver, nullptr)
1352 << "Cannot consume events from a window with no receiver";
1353 mInputReceiver->consumeCaptureEvent(hasCapture);
1354 }
1355
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001356 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1357 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001358 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001359 ASSERT_THAT(*motionEvent, matcher);
1360 }
1361
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001362 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001363 std::optional<int32_t> expectedDisplayId,
1364 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001365 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1366 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1367 expectedFlags);
1368 }
1369
arthurhungb89ccb02020-12-30 16:19:01 +08001370 void consumeDragEvent(bool isExiting, float x, float y) {
1371 mInputReceiver->consumeDragEvent(isExiting, x, y);
1372 }
1373
Antonio Kantekf16f2832021-09-28 04:39:20 +00001374 void consumeTouchModeEvent(bool inTouchMode) {
1375 ASSERT_NE(mInputReceiver, nullptr)
1376 << "Cannot consume events from a window with no receiver";
1377 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1378 }
1379
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001380 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001381 if (mInputReceiver == nullptr) {
1382 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1383 return std::nullopt;
1384 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001385 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001386 }
1387
1388 void finishEvent(uint32_t sequenceNum) {
1389 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1390 mInputReceiver->finishEvent(sequenceNum);
1391 }
1392
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001393 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1394 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1395 mInputReceiver->sendTimeline(inputEventId, timeline);
1396 }
1397
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001398 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001399 if (mInputReceiver == nullptr) {
1400 return nullptr;
1401 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001402 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001403 }
1404
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001405 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001406 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001407 if (event == nullptr) {
1408 ADD_FAILURE() << "Consume failed : no event";
1409 return nullptr;
1410 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001411 if (event->getType() != InputEventType::MOTION) {
1412 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001413 return nullptr;
1414 }
1415 return static_cast<MotionEvent*>(event);
1416 }
1417
Arthur Hungb92218b2018-08-14 12:00:21 +08001418 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001419 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001420 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001421 return; // Can't receive events if the window does not have input channel
1422 }
1423 ASSERT_NE(nullptr, mInputReceiver)
1424 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001425 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001426 }
1427
chaviwaf87b3e2019-10-01 16:59:28 -07001428 sp<IBinder> getToken() { return mInfo.token; }
1429
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001430 const std::string& getName() { return mName; }
1431
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001432 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001433 mInfo.ownerPid = ownerPid;
1434 mInfo.ownerUid = ownerUid;
1435 }
1436
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001437 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001438
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001439 void destroyReceiver() { mInputReceiver = nullptr; }
1440
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001441 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1442
chaviwd1c23182019-12-20 18:44:56 -08001443private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001444 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001445 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001446 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001447 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001448 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001449};
1450
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001451std::atomic<int32_t> FakeWindowHandle::sId{1};
1452
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001453static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001454 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001455 int32_t displayId = ADISPLAY_ID_NONE,
1456 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001457 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001458 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001459 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001460 KeyEvent event;
1461 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1462
1463 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001464 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001465 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1466 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001467
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001468 if (!allowKeyRepeat) {
1469 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1470 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001471 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001472 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001473}
1474
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001475static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1476 InputEventInjectionResult result =
1477 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1478 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1479 if (result != InputEventInjectionResult::TIMED_OUT) {
1480 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1481 }
1482}
1483
1484static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001485 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001486 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001487}
1488
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001489// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1490// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1491// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001492static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1493 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001494 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001495 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001496 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001497}
1498
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001499static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001500 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001501 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001502}
1503
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001504static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001505 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001506 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001507 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001508 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001509 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1510 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001511}
1512
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001513static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001514 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1515 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001516 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001517 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1518 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001520 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001521 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001522 MotionEventBuilder motionBuilder =
1523 MotionEventBuilder(action, source)
1524 .displayId(displayId)
1525 .eventTime(eventTime)
1526 .rawXCursorPosition(cursorPosition.x)
1527 .rawYCursorPosition(cursorPosition.y)
1528 .pointer(
1529 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1530 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1531 motionBuilder.downTime(eventTime);
1532 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001533
1534 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001535 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1536 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001537}
1538
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001539static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1540 int32_t displayId,
1541 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001542 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001543}
1544
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001545static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1546 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001547 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001548 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001549}
1550
Jackal Guof9696682018-10-05 12:23:23 +08001551static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1552 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1553 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001554 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001555 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1556 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001557
1558 return args;
1559}
1560
Josep del Riob3981622023-04-18 15:49:45 +00001561static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1562 int32_t displayId = ADISPLAY_ID_NONE) {
1563 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1564 // Define a valid key event.
1565 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001566 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001567 currentTime);
1568
1569 return args;
1570}
1571
1572static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1573 int32_t displayId = ADISPLAY_ID_NONE) {
1574 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1575 // Define a valid key event.
1576 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001577 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001578 AMETA_NONE, currentTime);
1579
1580 return args;
1581}
1582
Prabir Pradhan678438e2023-04-13 19:32:51 +00001583[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1584 int32_t displayId,
1585 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001586 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001587 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1588 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1589 }
1590
chaviwd1c23182019-12-20 18:44:56 -08001591 PointerProperties pointerProperties[pointerCount];
1592 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001593
chaviwd1c23182019-12-20 18:44:56 -08001594 for (size_t i = 0; i < pointerCount; i++) {
1595 pointerProperties[i].clear();
1596 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001597 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001598
chaviwd1c23182019-12-20 18:44:56 -08001599 pointerCoords[i].clear();
1600 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1601 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1602 }
Jackal Guof9696682018-10-05 12:23:23 +08001603
1604 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1605 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001606 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001607 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1608 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001609 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001610 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001611 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001612 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001613
1614 return args;
1615}
1616
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001617static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1618 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1619}
1620
chaviwd1c23182019-12-20 18:44:56 -08001621static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1622 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1623}
1624
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001625static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1626 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001627 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001628}
1629
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001630} // namespace
1631
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001632/**
1633 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1634 * broken channel.
1635 */
1636TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1637 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1638 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001639 sp<FakeWindowHandle>::make(application, mDispatcher,
1640 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001641
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001642 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001643
1644 // Window closes its channel, but the window remains.
1645 window->destroyReceiver();
1646 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1647}
1648
Arthur Hungb92218b2018-08-14 12:00:21 +08001649TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001651 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1652 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001653
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001654 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001656 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001657 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001658
1659 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001660 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001661}
1662
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001663TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1666 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001667
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001668 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001669 // Inject a MotionEvent to an unknown display.
1670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001671 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1673
1674 // Window should receive motion event.
1675 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1676}
1677
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001678/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001679 * Calling onWindowInfosChanged once should not cause any issues.
1680 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001681 * called twice.
1682 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001683TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001685 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1686 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001689 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001692 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001694
1695 // Window should receive motion event.
1696 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1697}
1698
1699/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001700 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 */
1702TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1705 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714
1715 // Window should receive motion event.
1716 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1717}
1718
Arthur Hungb92218b2018-08-14 12:00:21 +08001719// The foreground window should receive the first touch down event.
1720TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001722 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001723 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001724 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001725 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001727 mDispatcher->onWindowInfosChanged(
1728 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001730 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001732
1733 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001734 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001735 windowSecond->assertNoEvents();
1736}
1737
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001738/**
1739 * Two windows: A top window, and a wallpaper behind the window.
1740 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1741 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001742 * 1. foregroundWindow <-- dup touch to wallpaper
1743 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001744 */
1745TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1747 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001748 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001749 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001750 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001751 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001752 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001753
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001754 mDispatcher->onWindowInfosChanged(
1755 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001757 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001758 {100, 200}))
1759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1760
1761 // Both foreground window and its wallpaper should receive the touch down
1762 foregroundWindow->consumeMotionDown();
1763 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1764
1765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001766 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001767 ADISPLAY_ID_DEFAULT, {110, 200}))
1768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1769
1770 foregroundWindow->consumeMotionMove();
1771 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1772
1773 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001774 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001775 foregroundWindow->consumeMotionCancel();
1776 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1777 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1778}
1779
1780/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001781 * Two fingers down on the window, and lift off the first finger.
1782 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1783 * contains a single pointer.
1784 */
1785TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1787 sp<FakeWindowHandle> window =
1788 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1789
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001790 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001791 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001792 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1793 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1794 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001795 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001796 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1797 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1798 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1799 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001800 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001801 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1802 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1803 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1804 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001805 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1806 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1807 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1808
1809 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001810 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001811 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1812 window->consumeMotionEvent(
1813 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1814}
1815
1816/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001817 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1818 * with the following differences:
1819 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1820 * clean up the connection.
1821 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1822 * Ensure that there's no crash in the dispatcher.
1823 */
1824TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1826 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001827 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001828 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001829 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001830 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001831 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001832
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001833 mDispatcher->onWindowInfosChanged(
1834 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001837 {100, 200}))
1838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1839
1840 // Both foreground window and its wallpaper should receive the touch down
1841 foregroundWindow->consumeMotionDown();
1842 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1843
1844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001845 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001846 ADISPLAY_ID_DEFAULT, {110, 200}))
1847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1848
1849 foregroundWindow->consumeMotionMove();
1850 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1851
1852 // Wallpaper closes its channel, but the window remains.
1853 wallpaperWindow->destroyReceiver();
1854 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1855
1856 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1857 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001858 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859 foregroundWindow->consumeMotionCancel();
1860}
1861
Arthur Hungc539dbb2022-12-08 07:45:36 +00001862class ShouldSplitTouchFixture : public InputDispatcherTest,
1863 public ::testing::WithParamInterface<bool> {};
1864INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1865 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001866/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001867 * A single window that receives touch (on top), and a wallpaper window underneath it.
1868 * The top window gets a multitouch gesture.
1869 * Ensure that wallpaper gets the same gesture.
1870 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001871TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001873 sp<FakeWindowHandle> foregroundWindow =
1874 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1875 foregroundWindow->setDupTouchToWallpaper(true);
1876 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877
1878 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001879 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001880 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001881
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001882 mDispatcher->onWindowInfosChanged(
1883 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001884
1885 // Touch down on top window
1886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001887 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 {100, 100}))
1889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1890
1891 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001892 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1894
1895 // Second finger down on the top window
1896 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001897 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001898 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001899 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1900 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901 .build();
1902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001903 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 InputEventInjectionSync::WAIT_FOR_RESULT))
1905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1906
Harry Cutts33476232023-01-30 19:57:29 +00001907 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1908 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001910
1911 const MotionEvent secondFingerUpEvent =
1912 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1913 .displayId(ADISPLAY_ID_DEFAULT)
1914 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001915 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1916 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001917 .build();
1918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001919 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001920 InputEventInjectionSync::WAIT_FOR_RESULT))
1921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1922 foregroundWindow->consumeMotionPointerUp(0);
1923 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1924
1925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001926 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001927 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1928 AINPUT_SOURCE_TOUCHSCREEN)
1929 .displayId(ADISPLAY_ID_DEFAULT)
1930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001931 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001932 .x(100)
1933 .y(100))
1934 .build(),
1935 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001936 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1937 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1938 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001939}
1940
1941/**
1942 * Two windows: a window on the left and window on the right.
1943 * A third window, wallpaper, is behind both windows, and spans both top windows.
1944 * The first touch down goes to the left window. A second pointer touches down on the right window.
1945 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1946 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1947 * ACTION_POINTER_DOWN(1).
1948 */
1949TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1951 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001952 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001953 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001954 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955
1956 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001957 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001959 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960
1961 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001962 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001964 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001966 mDispatcher->onWindowInfosChanged(
1967 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1968 {},
1969 0,
1970 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001971
1972 // Touch down on left window
1973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001974 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001975 {100, 100}))
1976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1977
1978 // Both foreground window and its wallpaper should receive the touch down
1979 leftWindow->consumeMotionDown();
1980 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1981
1982 // Second finger down on the right window
1983 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001984 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001986 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1987 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 .build();
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001990 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991 InputEventInjectionSync::WAIT_FOR_RESULT))
1992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1993
1994 leftWindow->consumeMotionMove();
1995 // Since the touch is split, right window gets ACTION_DOWN
1996 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001997 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 expectedWallpaperFlags);
1999
2000 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002001 mDispatcher->onWindowInfosChanged(
2002 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002003 leftWindow->consumeMotionCancel();
2004 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2005 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2006
2007 // The pointer that's still down on the right window moves, and goes to the right window only.
2008 // As far as the dispatcher's concerned though, both pointers are still present.
2009 const MotionEvent secondFingerMoveEvent =
2010 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2011 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002012 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2013 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014 .build();
2015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002016 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 InputEventInjectionSync::WAIT_FOR_RESULT));
2018 rightWindow->consumeMotionMove();
2019
2020 leftWindow->assertNoEvents();
2021 rightWindow->assertNoEvents();
2022 wallpaperWindow->assertNoEvents();
2023}
2024
Arthur Hungc539dbb2022-12-08 07:45:36 +00002025/**
2026 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2027 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2028 * The right window should receive ACTION_DOWN.
2029 */
2030TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002032 sp<FakeWindowHandle> leftWindow =
2033 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2034 leftWindow->setFrame(Rect(0, 0, 200, 200));
2035 leftWindow->setDupTouchToWallpaper(true);
2036 leftWindow->setSlippery(true);
2037
2038 sp<FakeWindowHandle> rightWindow =
2039 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2040 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002041
2042 sp<FakeWindowHandle> wallpaperWindow =
2043 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2044 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002045
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002046 mDispatcher->onWindowInfosChanged(
2047 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2048 {},
2049 0,
2050 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002051
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002054 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002057
2058 // Both foreground window and its wallpaper should receive the touch down
2059 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002060 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2061
Arthur Hungc539dbb2022-12-08 07:45:36 +00002062 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002064 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002066 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2067
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 leftWindow->consumeMotionCancel();
2069 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2070 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002071}
2072
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002073/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002074 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2075 * interactive, it might stop sending this flag.
2076 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2077 * to have a consistent input stream.
2078 *
2079 * Test procedure:
2080 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2081 * DOWN (new gesture).
2082 *
2083 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2084 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2085 *
2086 * We technically just need a single window here, but we are using two windows (spy on top and a
2087 * regular window below) to emulate the actual situation where it happens on the device.
2088 */
2089TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2091 sp<FakeWindowHandle> spyWindow =
2092 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2093 spyWindow->setFrame(Rect(0, 0, 200, 200));
2094 spyWindow->setTrustedOverlay(true);
2095 spyWindow->setSpy(true);
2096
2097 sp<FakeWindowHandle> window =
2098 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2099 window->setFrame(Rect(0, 0, 200, 200));
2100
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002101 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002102 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002103
2104 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002105 mDispatcher->notifyMotion(
2106 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2107 .deviceId(touchDeviceId)
2108 .policyFlags(DEFAULT_POLICY_FLAGS)
2109 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2110 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002111
Prabir Pradhan678438e2023-04-13 19:32:51 +00002112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2113 .deviceId(touchDeviceId)
2114 .policyFlags(DEFAULT_POLICY_FLAGS)
2115 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2116 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2117 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002118 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2119 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2120 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2121 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2122
2123 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002124 mDispatcher->notifyMotion(
2125 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2126 .deviceId(touchDeviceId)
2127 .policyFlags(0)
2128 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2129 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2130 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002131 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2132 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2133
2134 // We don't need to reset the device to reproduce the issue, but the reset event typically
2135 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002136 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002137
2138 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002139 mDispatcher->notifyMotion(
2140 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2141 .deviceId(touchDeviceId)
2142 .policyFlags(DEFAULT_POLICY_FLAGS)
2143 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2144 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002145 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2146 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2147
2148 // No more events
2149 spyWindow->assertNoEvents();
2150 window->assertNoEvents();
2151}
2152
2153/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002154 * Two windows: a window on the left and a window on the right.
2155 * Mouse is hovered from the right window into the left window.
2156 * Next, we tap on the left window, where the cursor was last seen.
2157 * The second tap is done onto the right window.
2158 * The mouse and tap are from two different devices.
2159 * We technically don't need to set the downtime / eventtime for these events, but setting these
2160 * explicitly helps during debugging.
2161 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2162 * In the buggy implementation, a tap on the right window would cause a crash.
2163 */
2164TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2166 sp<FakeWindowHandle> leftWindow =
2167 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2168 leftWindow->setFrame(Rect(0, 0, 200, 200));
2169
2170 sp<FakeWindowHandle> rightWindow =
2171 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2172 rightWindow->setFrame(Rect(200, 0, 400, 200));
2173
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002174 mDispatcher->onWindowInfosChanged(
2175 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002176 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2177 // stale.
2178 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2179 const int32_t mouseDeviceId = 6;
2180 const int32_t touchDeviceId = 4;
2181 // Move the cursor from right
2182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002183 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002184 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2185 AINPUT_SOURCE_MOUSE)
2186 .deviceId(mouseDeviceId)
2187 .downTime(baseTime + 10)
2188 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002190 .build()));
2191 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2192
2193 // .. to the left window
2194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002195 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002196 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2197 AINPUT_SOURCE_MOUSE)
2198 .deviceId(mouseDeviceId)
2199 .downTime(baseTime + 10)
2200 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002201 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002202 .build()));
2203 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2204 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2205 // Now tap the left window
2206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002207 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002208 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2209 AINPUT_SOURCE_TOUCHSCREEN)
2210 .deviceId(touchDeviceId)
2211 .downTime(baseTime + 40)
2212 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002213 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002214 .build()));
2215 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2216 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2217
2218 // release tap
2219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002220 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002221 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2222 AINPUT_SOURCE_TOUCHSCREEN)
2223 .deviceId(touchDeviceId)
2224 .downTime(baseTime + 40)
2225 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002226 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002227 .build()));
2228 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2229
2230 // Tap the window on the right
2231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002232 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002233 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2234 AINPUT_SOURCE_TOUCHSCREEN)
2235 .deviceId(touchDeviceId)
2236 .downTime(baseTime + 60)
2237 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002238 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002239 .build()));
2240 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2241
2242 // release tap
2243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002244 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002245 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2246 AINPUT_SOURCE_TOUCHSCREEN)
2247 .deviceId(touchDeviceId)
2248 .downTime(baseTime + 60)
2249 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002250 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002251 .build()));
2252 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2253
2254 // No more events
2255 leftWindow->assertNoEvents();
2256 rightWindow->assertNoEvents();
2257}
2258
2259/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002260 * Start hovering in a window. While this hover is still active, make another window appear on top.
2261 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2262 * While the top window is present, the hovering is stopped.
2263 * Later, hovering gets resumed again.
2264 * Ensure that new hover gesture is handled correctly.
2265 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2266 * to the window that's currently being hovered over.
2267 */
2268TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2269 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2270 sp<FakeWindowHandle> window =
2271 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2272 window->setFrame(Rect(0, 0, 200, 200));
2273
2274 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002275 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002276
2277 // Start hovering in the window
2278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2279 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2280 .build());
2281 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2282
2283 // Now, an obscuring window appears!
2284 sp<FakeWindowHandle> obscuringWindow =
2285 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2286 ADISPLAY_ID_DEFAULT,
2287 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2288 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2289 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2290 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2291 obscuringWindow->setNoInputChannel(true);
2292 obscuringWindow->setFocusable(false);
2293 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002294 mDispatcher->onWindowInfosChanged(
2295 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002296
2297 // While this new obscuring window is present, the hovering is stopped
2298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2299 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2300 .build());
2301 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2302
2303 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002304 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002305
2306 // And a new hover gesture starts.
2307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2308 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2309 .build());
2310 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2311}
2312
2313/**
2314 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2315 * the obscuring window.
2316 */
2317TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2319 sp<FakeWindowHandle> window =
2320 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2321 window->setFrame(Rect(0, 0, 200, 200));
2322
2323 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002324 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002325
2326 // Start hovering in the window
2327 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2328 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2329 .build());
2330 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2331
2332 // Now, an obscuring window appears!
2333 sp<FakeWindowHandle> obscuringWindow =
2334 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2335 ADISPLAY_ID_DEFAULT,
2336 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2337 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2338 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2339 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2340 obscuringWindow->setNoInputChannel(true);
2341 obscuringWindow->setFocusable(false);
2342 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002343 mDispatcher->onWindowInfosChanged(
2344 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002345
2346 // While this new obscuring window is present, the hovering continues. The event can't go to the
2347 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2349 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2350 .build());
2351 obscuringWindow->assertNoEvents();
2352 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2353
2354 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002355 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002356
2357 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2358 // so it should generate a HOVER_ENTER
2359 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2360 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2361 .build());
2362 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2363
2364 // Now the MOVE should be getting dispatched normally
2365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2366 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2367 .build());
2368 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2369}
2370
2371/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002372 * Two windows: a window on the left and a window on the right.
2373 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2374 * down. Then, on the left window, also place second touch pointer down.
2375 * This test tries to reproduce a crash.
2376 * In the buggy implementation, second pointer down on the left window would cause a crash.
2377 */
2378TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2380 sp<FakeWindowHandle> leftWindow =
2381 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2382 leftWindow->setFrame(Rect(0, 0, 200, 200));
2383
2384 sp<FakeWindowHandle> rightWindow =
2385 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2386 rightWindow->setFrame(Rect(200, 0, 400, 200));
2387
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002388 mDispatcher->onWindowInfosChanged(
2389 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002390
2391 const int32_t touchDeviceId = 4;
2392 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002393
2394 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2396 .deviceId(mouseDeviceId)
2397 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2398 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002399 leftWindow->consumeMotionEvent(
2400 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2401
2402 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2404 .deviceId(mouseDeviceId)
2405 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2406 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2407 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002408
2409 leftWindow->consumeMotionEvent(
2410 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2411 leftWindow->consumeMotionEvent(
2412 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2413
Prabir Pradhan678438e2023-04-13 19:32:51 +00002414 mDispatcher->notifyMotion(
2415 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2416 .deviceId(mouseDeviceId)
2417 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2418 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2420 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002421 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2422
2423 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002424 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2425 .deviceId(touchDeviceId)
2426 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2427 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002428 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2429
2430 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2431
2432 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002433 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2434 .deviceId(touchDeviceId)
2435 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2436 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2437 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002438 leftWindow->consumeMotionEvent(
2439 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2440 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2441 // current implementation.
2442 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2443 rightWindow->consumeMotionEvent(
2444 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2445
2446 leftWindow->assertNoEvents();
2447 rightWindow->assertNoEvents();
2448}
2449
2450/**
2451 * On a single window, use two different devices: mouse and touch.
2452 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2453 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2454 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2455 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2456 * represent a new gesture.
2457 */
2458TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2459 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2460 sp<FakeWindowHandle> window =
2461 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2462 window->setFrame(Rect(0, 0, 400, 400));
2463
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002464 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002465
2466 const int32_t touchDeviceId = 4;
2467 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002468
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002469 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2471 .deviceId(touchDeviceId)
2472 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2473 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002474 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002475 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2476 .deviceId(touchDeviceId)
2477 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2478 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2479 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002480 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002481 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2482 .deviceId(touchDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2484 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2485 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002486 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2487 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2488 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2489
2490 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2492 .deviceId(mouseDeviceId)
2493 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2494 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2495 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002496
2497 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002498 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002499 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2500
Prabir Pradhan678438e2023-04-13 19:32:51 +00002501 mDispatcher->notifyMotion(
2502 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2503 .deviceId(mouseDeviceId)
2504 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2505 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2506 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2507 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002508 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2509
2510 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002511 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2512 .deviceId(touchDeviceId)
2513 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2514 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002516 // The pointer_down event should be ignored
2517 window->assertNoEvents();
2518}
2519
2520/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002521 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2522 * the injected event.
2523 */
2524TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2526 sp<FakeWindowHandle> window =
2527 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2528 window->setFrame(Rect(0, 0, 400, 400));
2529
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002530 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002531
2532 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002533 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2534 // completion.
2535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002536 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002537 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2538 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002539 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002540 .build()));
2541 window->consumeMotionEvent(
2542 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2543
2544 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2545 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2547 .deviceId(touchDeviceId)
2548 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2549 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002550
2551 window->consumeMotionEvent(
2552 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2553 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2554}
2555
2556/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002557 * This test is similar to the test above, but the sequence of injected events is different.
2558 *
2559 * Two windows: a window on the left and a window on the right.
2560 * Mouse is hovered over the left window.
2561 * Next, we tap on the left window, where the cursor was last seen.
2562 *
2563 * After that, we inject one finger down onto the right window, and then a second finger down onto
2564 * the left window.
2565 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2566 * window (first), and then another on the left window (second).
2567 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2568 * In the buggy implementation, second finger down on the left window would cause a crash.
2569 */
2570TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2572 sp<FakeWindowHandle> leftWindow =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2574 leftWindow->setFrame(Rect(0, 0, 200, 200));
2575
2576 sp<FakeWindowHandle> rightWindow =
2577 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2578 rightWindow->setFrame(Rect(200, 0, 400, 200));
2579
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002580 mDispatcher->onWindowInfosChanged(
2581 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002582
2583 const int32_t mouseDeviceId = 6;
2584 const int32_t touchDeviceId = 4;
2585 // Hover over the left window. Keep the cursor there.
2586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002587 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002588 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2589 AINPUT_SOURCE_MOUSE)
2590 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002591 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002592 .build()));
2593 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2594
2595 // Tap on left window
2596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002597 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002598 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2599 AINPUT_SOURCE_TOUCHSCREEN)
2600 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002601 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002602 .build()));
2603
2604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002605 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002606 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2607 AINPUT_SOURCE_TOUCHSCREEN)
2608 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002609 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002610 .build()));
2611 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2612 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2613 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2614
2615 // First finger down on right window
2616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002617 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002618 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2619 AINPUT_SOURCE_TOUCHSCREEN)
2620 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002621 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002622 .build()));
2623 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2624
2625 // Second finger down on the left window
2626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002627 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002628 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2629 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002630 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2631 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002632 .build()));
2633 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2634 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2635
2636 // No more events
2637 leftWindow->assertNoEvents();
2638 rightWindow->assertNoEvents();
2639}
2640
2641/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002642 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2643 * While the touch is down, new hover events from the stylus device should be ignored. After the
2644 * touch is gone, stylus hovering should start working again.
2645 */
2646TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2648 sp<FakeWindowHandle> window =
2649 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2650 window->setFrame(Rect(0, 0, 200, 200));
2651
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002652 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002653
2654 const int32_t stylusDeviceId = 5;
2655 const int32_t touchDeviceId = 4;
2656 // Start hovering with stylus
2657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002658 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002659 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2660 AINPUT_SOURCE_STYLUS)
2661 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002662 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002663 .build()));
2664 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2665
2666 // Finger down on the window
2667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002668 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002669 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2670 AINPUT_SOURCE_TOUCHSCREEN)
2671 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002672 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002673 .build()));
2674 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2675 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2676
2677 // Try to continue hovering with stylus. Since we are already down, injection should fail
2678 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002679 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002680 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2681 AINPUT_SOURCE_STYLUS)
2682 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002683 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002684 .build()));
2685 // No event should be sent. This event should be ignored because a pointer from another device
2686 // is already down.
2687
2688 // Lift up the finger
2689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002690 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002691 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2692 AINPUT_SOURCE_TOUCHSCREEN)
2693 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002694 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002695 .build()));
2696 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2697
2698 // Now that the touch is gone, stylus hovering should start working again
2699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002700 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002701 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2702 AINPUT_SOURCE_STYLUS)
2703 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002704 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002705 .build()));
2706 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2707 // No more events
2708 window->assertNoEvents();
2709}
2710
2711/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002712 * A spy window above a window with no input channel.
2713 * Start hovering with a stylus device, and then tap with it.
2714 * Ensure spy window receives the entire sequence.
2715 */
2716TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2718 sp<FakeWindowHandle> spyWindow =
2719 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2720 spyWindow->setFrame(Rect(0, 0, 200, 200));
2721 spyWindow->setTrustedOverlay(true);
2722 spyWindow->setSpy(true);
2723 sp<FakeWindowHandle> window =
2724 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2725 window->setNoInputChannel(true);
2726 window->setFrame(Rect(0, 0, 200, 200));
2727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002728 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002729
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002730 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2732 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2733 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002734 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2735 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2737 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2738 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002739 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2740
2741 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2744 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002745 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2746
2747 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2749 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2750 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002751 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2752
2753 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002754 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2755 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2756 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002757 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2758 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002759 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2760 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2761 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002762 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2763
2764 // No more events
2765 spyWindow->assertNoEvents();
2766 window->assertNoEvents();
2767}
2768
2769/**
2770 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2771 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2772 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2773 * While the mouse is down, new move events from the touch device should be ignored.
2774 */
2775TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2777 sp<FakeWindowHandle> spyWindow =
2778 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2779 spyWindow->setFrame(Rect(0, 0, 200, 200));
2780 spyWindow->setTrustedOverlay(true);
2781 spyWindow->setSpy(true);
2782 sp<FakeWindowHandle> window =
2783 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2784 window->setFrame(Rect(0, 0, 200, 200));
2785
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002786 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002787
2788 const int32_t mouseDeviceId = 7;
2789 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002790
2791 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002792 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2793 .deviceId(mouseDeviceId)
2794 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2795 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002796 spyWindow->consumeMotionEvent(
2797 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2798 window->consumeMotionEvent(
2799 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2800
2801 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2803 .deviceId(touchDeviceId)
2804 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2805 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002806 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2807 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2808 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2809 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2810
Prabir Pradhan678438e2023-04-13 19:32:51 +00002811 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2812 .deviceId(touchDeviceId)
2813 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2814 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2816 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2817
2818 // Pilfer the stream
2819 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2820 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2821
Prabir Pradhan678438e2023-04-13 19:32:51 +00002822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2823 .deviceId(touchDeviceId)
2824 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2825 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002826 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2827
2828 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2830 .deviceId(mouseDeviceId)
2831 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2832 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2833 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002834
2835 spyWindow->consumeMotionEvent(
2836 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2837 spyWindow->consumeMotionEvent(
2838 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2839 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2840
Prabir Pradhan678438e2023-04-13 19:32:51 +00002841 mDispatcher->notifyMotion(
2842 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2843 .deviceId(mouseDeviceId)
2844 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2845 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2846 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2847 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002848 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2849 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2850
2851 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2853 .deviceId(mouseDeviceId)
2854 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2855 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2856 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002857 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2858 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2859
2860 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002861 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2862 .deviceId(touchDeviceId)
2863 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2864 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865
2866 // No more events
2867 spyWindow->assertNoEvents();
2868 window->assertNoEvents();
2869}
2870
2871/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002872 * On the display, have a single window, and also an area where there's no window.
2873 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2874 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2875 */
2876TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2878 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002879 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002880
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002882
2883 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002884 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002885
2886 mDispatcher->waitForIdle();
2887 window->assertNoEvents();
2888
2889 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002890 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002891 mDispatcher->waitForIdle();
2892 window->consumeMotionDown();
2893}
2894
2895/**
2896 * Same test as above, but instead of touching the empty space, the first touch goes to
2897 * non-touchable window.
2898 */
2899TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2901 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002902 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002903 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2904 window1->setTouchable(false);
2905 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002906 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002907 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2908
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002909 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002910
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002911 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002912 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002913
2914 mDispatcher->waitForIdle();
2915 window1->assertNoEvents();
2916 window2->assertNoEvents();
2917
2918 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002919 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002920 mDispatcher->waitForIdle();
2921 window2->consumeMotionDown();
2922}
2923
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002924/**
2925 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2926 * to the event time of the first ACTION_DOWN sent to the particular window.
2927 */
2928TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2929 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2930 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002931 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002932 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2933 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002934 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002935 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2936
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002937 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002938
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002939 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002940 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002941
2942 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002943
2944 MotionEvent* motionEvent1 = window1->consumeMotion();
2945 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002946 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002947 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
2948 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002949
2950 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002951 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002952 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002953 MotionEvent* motionEvent2 = window2->consumeMotion();
2954 ASSERT_NE(motionEvent2, nullptr);
2955 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002956 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002957 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002958
2959 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002960 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002961 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002962 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002963
2964 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002965 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002966 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002967 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002968
2969 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2970 window1->consumeMotionMove();
2971 window1->assertNoEvents();
2972
2973 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002974 mDispatcher->notifyMotion(
2975 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002976 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002977 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002978
Prabir Pradhan678438e2023-04-13 19:32:51 +00002979 mDispatcher->notifyMotion(
2980 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002981 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002982 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002983}
2984
Garfield Tandf26e862020-07-01 20:18:19 -07002985TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002987 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002988 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002989 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002990 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002991 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002992 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002993
2994 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002996 mDispatcher->onWindowInfosChanged(
2997 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07002998
2999 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003001 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003002 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3003 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003004 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003005 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003006 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003007
3008 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003010 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003011 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3012 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003013 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003014 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003015 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3016 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003017
3018 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003020 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003021 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3022 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003024 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003025 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3026 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003027
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003029 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003030 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3031 AINPUT_SOURCE_MOUSE)
3032 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3033 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003034 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003035 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003036 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003037
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003039 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003040 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3041 AINPUT_SOURCE_MOUSE)
3042 .buttonState(0)
3043 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003045 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003046 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003047
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003049 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003050 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3051 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003052 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003053 .build()));
3054 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3055
3056 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003058 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003059 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3060 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003061 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003062 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003063 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003064
3065 // No more events
3066 windowLeft->assertNoEvents();
3067 windowRight->assertNoEvents();
3068}
3069
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003070/**
3071 * Put two fingers down (and don't release them) and click the mouse button.
3072 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3073 * currently active gesture should be canceled, and the new one should proceed.
3074 */
3075TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3077 sp<FakeWindowHandle> window =
3078 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3079 window->setFrame(Rect(0, 0, 600, 800));
3080
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003081 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003082
3083 const int32_t touchDeviceId = 4;
3084 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003085
3086 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003087 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3088 .deviceId(touchDeviceId)
3089 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3090 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091
Prabir Pradhan678438e2023-04-13 19:32:51 +00003092 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3093 .deviceId(touchDeviceId)
3094 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3095 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3096 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003097 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3098 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3099
3100 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3102 .deviceId(mouseDeviceId)
3103 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3104 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3107 WithPointerCount(2u)));
3108 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3109
Prabir Pradhan678438e2023-04-13 19:32:51 +00003110 mDispatcher->notifyMotion(
3111 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3112 .deviceId(mouseDeviceId)
3113 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3114 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3115 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3116 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003117 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3118
3119 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3120 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3122 .deviceId(touchDeviceId)
3123 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3124 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3125 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003126 window->assertNoEvents();
3127}
3128
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003129TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3131
3132 sp<FakeWindowHandle> spyWindow =
3133 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3134 spyWindow->setFrame(Rect(0, 0, 600, 800));
3135 spyWindow->setTrustedOverlay(true);
3136 spyWindow->setSpy(true);
3137 sp<FakeWindowHandle> window =
3138 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3139 window->setFrame(Rect(0, 0, 600, 800));
3140
3141 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003142 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003143
3144 // Send mouse cursor to the window
3145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003146 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003147 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3148 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003149 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003150 .build()));
3151
3152 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3153 WithSource(AINPUT_SOURCE_MOUSE)));
3154 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3155 WithSource(AINPUT_SOURCE_MOUSE)));
3156
3157 window->assertNoEvents();
3158 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003159}
3160
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003161TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3162 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3163
3164 sp<FakeWindowHandle> spyWindow =
3165 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3166 spyWindow->setFrame(Rect(0, 0, 600, 800));
3167 spyWindow->setTrustedOverlay(true);
3168 spyWindow->setSpy(true);
3169 sp<FakeWindowHandle> window =
3170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3171 window->setFrame(Rect(0, 0, 600, 800));
3172
3173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003174 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003175
3176 // Send mouse cursor to the window
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003179 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3180 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003181 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003182 .build()));
3183
3184 // Move mouse cursor
3185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003186 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003187 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3188 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003190 .build()));
3191
3192 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3193 WithSource(AINPUT_SOURCE_MOUSE)));
3194 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3195 WithSource(AINPUT_SOURCE_MOUSE)));
3196 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3197 WithSource(AINPUT_SOURCE_MOUSE)));
3198 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3199 WithSource(AINPUT_SOURCE_MOUSE)));
3200 // Touch down on the window
3201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003202 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003203 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3204 AINPUT_SOURCE_TOUCHSCREEN)
3205 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003206 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003207 .build()));
3208 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3209 WithSource(AINPUT_SOURCE_MOUSE)));
3210 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3211 WithSource(AINPUT_SOURCE_MOUSE)));
3212 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3213 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3214 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3215 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3216
3217 // pilfer the motion, retaining the gesture on the spy window.
3218 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3219 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3220 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3221
3222 // Touch UP on the window
3223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003224 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003225 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3226 AINPUT_SOURCE_TOUCHSCREEN)
3227 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003228 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003229 .build()));
3230 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3231 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3232
3233 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3234 // to send a new gesture. It should again go to both windows (spy and the window below), just
3235 // like the first gesture did, before pilfering. The window configuration has not changed.
3236
3237 // One more tap - DOWN
3238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003240 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3241 AINPUT_SOURCE_TOUCHSCREEN)
3242 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003243 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003244 .build()));
3245 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3246 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3247 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3248 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3249
3250 // Touch UP on the window
3251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003252 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003253 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3254 AINPUT_SOURCE_TOUCHSCREEN)
3255 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003256 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003257 .build()));
3258 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3259 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3260 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3261 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3262
3263 window->assertNoEvents();
3264 spyWindow->assertNoEvents();
3265}
3266
Garfield Tandf26e862020-07-01 20:18:19 -07003267// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3268// directly in this test.
3269TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003271 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003272 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003273 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003274
3275 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3276
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003277 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003278
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003280 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003281 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3282 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003283 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003284 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003285 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003286 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003288 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003289 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3290 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003291 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003292 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003293 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3294 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003295
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003297 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003298 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3299 AINPUT_SOURCE_MOUSE)
3300 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3301 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003302 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003303 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003304 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003305
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003307 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003308 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3309 AINPUT_SOURCE_MOUSE)
3310 .buttonState(0)
3311 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003312 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003313 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003314 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003315
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003317 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003318 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3319 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003321 .build()));
3322 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3323
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003324 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3325 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3326 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003327 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003328 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3329 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003330 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003331 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003332 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003333}
3334
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003335/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003336 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3337 * is generated.
3338 */
3339TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3341 sp<FakeWindowHandle> window =
3342 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3343 window->setFrame(Rect(0, 0, 1200, 800));
3344
3345 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3346
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003347 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003348
3349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003350 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003351 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3352 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003353 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003354 .build()));
3355 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3356
3357 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003358 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003359 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3360}
3361
3362/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003363 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3364 */
3365TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3367 sp<FakeWindowHandle> window =
3368 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3369 window->setFrame(Rect(0, 0, 1200, 800));
3370
3371 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3372
3373 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3374
3375 MotionEventBuilder hoverEnterBuilder =
3376 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3377 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3378 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3380 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3382 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3383 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3384 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3385}
3386
3387/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003388 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3389 */
3390TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3391 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3392 sp<FakeWindowHandle> window =
3393 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3394 window->setFrame(Rect(0, 0, 100, 100));
3395
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003396 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003397
3398 const int32_t mouseDeviceId = 7;
3399 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003400
3401 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3403 .deviceId(mouseDeviceId)
3404 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3405 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003406 window->consumeMotionEvent(
3407 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3408
3409 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003410 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3411 .deviceId(touchDeviceId)
3412 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3413 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003414
3415 window->consumeMotionEvent(
3416 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3417 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3418}
3419
3420/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003421 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003422 * The tap causes a HOVER_EXIT event to be generated because the current event
3423 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003424 */
3425TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3427 sp<FakeWindowHandle> window =
3428 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3429 window->setFrame(Rect(0, 0, 100, 100));
3430
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003431 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003432
3433 // Inject a hover_move from mouse.
3434 NotifyMotionArgs motionArgs =
3435 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3436 ADISPLAY_ID_DEFAULT, {{50, 50}});
3437 motionArgs.xCursorPosition = 50;
3438 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003439 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003440 ASSERT_NO_FATAL_FAILURE(
3441 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3442 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003443
3444 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003445 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3446 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3447 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003448 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003449 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3450 WithSource(AINPUT_SOURCE_MOUSE))));
3451
3452 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003453 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3454 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3455
Prabir Pradhan678438e2023-04-13 19:32:51 +00003456 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3457 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003458 ASSERT_NO_FATAL_FAILURE(
3459 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3460 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3461}
3462
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003463TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3465 sp<FakeWindowHandle> windowDefaultDisplay =
3466 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3467 ADISPLAY_ID_DEFAULT);
3468 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3469 sp<FakeWindowHandle> windowSecondDisplay =
3470 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3471 SECOND_DISPLAY_ID);
3472 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3473
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003474 mDispatcher->onWindowInfosChanged(
3475 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003476
3477 // Set cursor position in window in default display and check that hover enter and move
3478 // events are generated.
3479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003480 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003481 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3482 AINPUT_SOURCE_MOUSE)
3483 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003484 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003485 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003486 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003487
3488 // Remove all windows in secondary display and check that no event happens on window in
3489 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003490 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3491
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003492 windowDefaultDisplay->assertNoEvents();
3493
3494 // Move cursor position in window in default display and check that only hover move
3495 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003496 mDispatcher->onWindowInfosChanged(
3497 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003499 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003500 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3501 AINPUT_SOURCE_MOUSE)
3502 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003503 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003504 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003505 windowDefaultDisplay->consumeMotionEvent(
3506 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3507 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003508 windowDefaultDisplay->assertNoEvents();
3509}
3510
Garfield Tan00f511d2019-06-12 16:55:40 -07003511TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003513
3514 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003515 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003516 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003517 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003518 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003519 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003520
3521 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3522
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003523 mDispatcher->onWindowInfosChanged(
3524 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003525
3526 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3527 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003529 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003530 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003531 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003532 windowRight->assertNoEvents();
3533}
3534
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003535TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003536 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003537 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3538 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003539 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003540
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003541 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003542 setFocusedWindow(window);
3543
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003544 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003545
Prabir Pradhan678438e2023-04-13 19:32:51 +00003546 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003547
3548 // Window should receive key down event.
3549 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3550
3551 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3552 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003553 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003554 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003555 AKEY_EVENT_FLAG_CANCELED);
3556}
3557
3558TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003560 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3561 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003562
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003564
Prabir Pradhan678438e2023-04-13 19:32:51 +00003565 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3566 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003567
3568 // Window should receive motion down event.
3569 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3570
3571 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3572 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003573 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003574 window->consumeMotionEvent(
3575 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003576}
3577
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003578TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3580 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3581 "Fake Window", ADISPLAY_ID_DEFAULT);
3582
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003583 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003584
3585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3586 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3587 .build());
3588
3589 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3590
3591 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3592 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3593 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3594
3595 // After the device has been reset, a new hovering stream can be sent to the window
3596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3597 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3598 .build());
3599 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3600}
3601
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003602TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003604 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3605 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003606 window->setFocusable(true);
3607
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003608 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003609 setFocusedWindow(window);
3610
3611 window->consumeFocusEvent(true);
3612
Prabir Pradhan678438e2023-04-13 19:32:51 +00003613 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003614 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3615 const nsecs_t injectTime = keyArgs.eventTime;
3616 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003617 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003618 // The dispatching time should be always greater than or equal to intercept key timeout.
3619 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3620 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3621 std::chrono::nanoseconds(interceptKeyTimeout).count());
3622}
3623
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003624/**
3625 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3626 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003627TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003629 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3630 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003631 window->setFocusable(true);
3632
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003633 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003634 setFocusedWindow(window);
3635
3636 window->consumeFocusEvent(true);
3637
Prabir Pradhan678438e2023-04-13 19:32:51 +00003638 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003639 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003640
3641 // Set a value that's significantly larger than the default consumption timeout. If the
3642 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3643 mFakePolicy->setInterceptKeyTimeout(600ms);
3644 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3645 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003646 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3647}
3648
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003649/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003650 * Two windows. First is a regular window. Second does not overlap with the first, and has
3651 * WATCH_OUTSIDE_TOUCH.
3652 * Both windows are owned by the same UID.
3653 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3654 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3655 */
3656TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3658 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3659 "First Window", ADISPLAY_ID_DEFAULT);
3660 window->setFrame(Rect{0, 0, 100, 100});
3661
3662 sp<FakeWindowHandle> outsideWindow =
3663 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3664 ADISPLAY_ID_DEFAULT);
3665 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3666 outsideWindow->setWatchOutsideTouch(true);
3667 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003668 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003669
3670 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003671 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3672 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3673 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003674 window->consumeMotionDown();
3675 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3676 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3677 outsideWindow->consumeMotionEvent(
3678 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3679}
3680
3681/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003682 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3683 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3684 * ACTION_OUTSIDE event is sent per gesture.
3685 */
3686TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3687 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003689 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3690 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003691 window->setWatchOutsideTouch(true);
3692 window->setFrame(Rect{0, 0, 100, 100});
3693 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003694 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3695 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003696 secondWindow->setFrame(Rect{100, 100, 200, 200});
3697 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003698 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3699 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003700 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003701 mDispatcher->onWindowInfosChanged(
3702 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003703
3704 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003705 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3706 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3707 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003708 window->assertNoEvents();
3709 secondWindow->assertNoEvents();
3710
3711 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3712 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003713 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3714 ADISPLAY_ID_DEFAULT,
3715 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003716 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3717 window->consumeMotionEvent(
3718 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003719 secondWindow->consumeMotionDown();
3720 thirdWindow->assertNoEvents();
3721
3722 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3723 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003724 mDispatcher->notifyMotion(
3725 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3726 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003727 window->assertNoEvents();
3728 secondWindow->consumeMotionMove();
3729 thirdWindow->consumeMotionDown();
3730}
3731
Prabir Pradhan814fe082022-07-22 20:22:18 +00003732TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003734 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3735 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003736 window->setFocusable(true);
3737
Patrick Williamsd828f302023-04-28 17:52:08 -05003738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003739 setFocusedWindow(window);
3740
3741 window->consumeFocusEvent(true);
3742
Prabir Pradhan678438e2023-04-13 19:32:51 +00003743 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3744 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3745 mDispatcher->notifyKey(keyDown);
3746 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003747
3748 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3749 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3750
3751 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003752 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003753
3754 window->consumeFocusEvent(false);
3755
Prabir Pradhan678438e2023-04-13 19:32:51 +00003756 mDispatcher->notifyKey(keyDown);
3757 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003758 window->assertNoEvents();
3759}
3760
Arthur Hung96483742022-11-15 03:30:48 +00003761TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3763 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3764 "Fake Window", ADISPLAY_ID_DEFAULT);
3765 // Ensure window is non-split and have some transform.
3766 window->setPreventSplitting(true);
3767 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003768 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003769
3770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003771 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00003772 {50, 50}))
3773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3774 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3775
3776 const MotionEvent secondFingerDownEvent =
3777 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3778 .displayId(ADISPLAY_ID_DEFAULT)
3779 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003780 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3781 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003782 .build();
3783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003784 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00003785 InputEventInjectionSync::WAIT_FOR_RESULT))
3786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3787
3788 const MotionEvent* event = window->consumeMotion();
3789 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3790 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3791 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3792 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3793 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3794}
3795
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003796/**
3797 * Two windows: a splittable and a non-splittable.
3798 * The non-splittable window shouldn't receive any "incomplete" gestures.
3799 * Send the first pointer to the splittable window, and then touch the non-splittable window.
3800 * The second pointer should be dropped because the initial window is splittable, so it won't get
3801 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
3802 * "incomplete" gestures.
3803 */
3804TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
3805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3806 sp<FakeWindowHandle> leftWindow =
3807 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
3808 ADISPLAY_ID_DEFAULT);
3809 leftWindow->setPreventSplitting(false);
3810 leftWindow->setFrame(Rect(0, 0, 100, 100));
3811 sp<FakeWindowHandle> rightWindow =
3812 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
3813 ADISPLAY_ID_DEFAULT);
3814 rightWindow->setPreventSplitting(true);
3815 rightWindow->setFrame(Rect(100, 100, 200, 200));
3816 mDispatcher->onWindowInfosChanged(
3817 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3818
3819 // Touch down on left, splittable window
3820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3821 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3822 .build());
3823 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3824
3825 mDispatcher->notifyMotion(
3826 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3827 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3828 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
3829 .build());
3830 leftWindow->assertNoEvents();
3831 rightWindow->assertNoEvents();
3832}
3833
Harry Cuttsb166c002023-05-09 13:06:05 +00003834TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3836 sp<FakeWindowHandle> window =
3837 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3838 window->setFrame(Rect(0, 0, 400, 400));
3839 sp<FakeWindowHandle> trustedOverlay =
3840 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3841 ADISPLAY_ID_DEFAULT);
3842 trustedOverlay->setSpy(true);
3843 trustedOverlay->setTrustedOverlay(true);
3844
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003845 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003846
3847 // Start a three-finger touchpad swipe
3848 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3849 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3850 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3851 .build());
3852 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3853 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3854 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3855 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3856 .build());
3857 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3858 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3859 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3860 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3861 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3862 .build());
3863
3864 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3865 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3866 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3867
3868 // Move the swipe a bit
3869 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3870 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3871 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3872 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3873 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3874 .build());
3875
3876 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3877
3878 // End the swipe
3879 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3880 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3881 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3882 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3883 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3884 .build());
3885 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3886 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3887 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3888 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3889 .build());
3890 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3891 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3892 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3893 .build());
3894
3895 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3896 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3897 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3898
3899 window->assertNoEvents();
3900}
3901
3902TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3904 sp<FakeWindowHandle> window =
3905 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3906 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003907 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00003908
3909 // Start a three-finger touchpad swipe
3910 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3911 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3912 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3913 .build());
3914 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3915 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3916 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3917 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3918 .build());
3919 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3920 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3921 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3922 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3923 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3924 .build());
3925
3926 // Move the swipe a bit
3927 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3928 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3929 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3930 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3931 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3932 .build());
3933
3934 // End the swipe
3935 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3936 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3937 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3938 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3939 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3940 .build());
3941 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3942 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3943 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3944 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3945 .build());
3946 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3947 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3948 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3949 .build());
3950
3951 window->assertNoEvents();
3952}
3953
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003954/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003955 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3956 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003957 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003958 */
3959TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3960 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3961 sp<FakeWindowHandle> window =
3962 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3963 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003964 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003965
3966 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3968 .downTime(baseTime + 10)
3969 .eventTime(baseTime + 10)
3970 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3971 .build());
3972
3973 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3974
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003975 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003976 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003977
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003979
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003980 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3981 .downTime(baseTime + 10)
3982 .eventTime(baseTime + 30)
3983 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3984 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3985 .build());
3986
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003987 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3988
3989 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003990 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3991 .downTime(baseTime + 10)
3992 .eventTime(baseTime + 40)
3993 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3994 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3995 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003996
3997 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3998
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003999 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4000 .downTime(baseTime + 10)
4001 .eventTime(baseTime + 50)
4002 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4003 .build());
4004
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004005 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4006
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004007 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4008 .downTime(baseTime + 60)
4009 .eventTime(baseTime + 60)
4010 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4011 .build());
4012
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004013 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004014}
4015
4016/**
Hu Guo771a7692023-09-17 20:51:08 +08004017 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4018 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4019 * its coordinates should be converted by the transform of the windows of target screen.
4020 */
4021TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4022 // This case will create a window and a spy window on the default display and mirror
4023 // window on the second display. cancel event is sent through spy window pilferPointers
4024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4025
4026 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4027 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4028 spyWindowDefaultDisplay->setTrustedOverlay(true);
4029 spyWindowDefaultDisplay->setSpy(true);
4030
4031 sp<FakeWindowHandle> windowDefaultDisplay =
4032 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4033 ADISPLAY_ID_DEFAULT);
4034 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4035
4036 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4037 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4038
4039 // Add the windows to the dispatcher
4040 mDispatcher->onWindowInfosChanged(
4041 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4042 *windowSecondDisplay->getInfo()},
4043 {},
4044 0,
4045 0});
4046
4047 // Send down to ADISPLAY_ID_DEFAULT
4048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4049 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4050 {100, 100}))
4051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4052
4053 spyWindowDefaultDisplay->consumeMotionDown();
4054 windowDefaultDisplay->consumeMotionDown();
4055
4056 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4057
4058 // windowDefaultDisplay gets cancel
4059 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4060 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4061
4062 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4063 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4064 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4065 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4066 EXPECT_EQ(100, event->getX(0));
4067 EXPECT_EQ(100, event->getY(0));
4068}
4069
4070/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004071 * Ensure the correct coordinate spaces are used by InputDispatcher.
4072 *
4073 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4074 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4075 * space.
4076 */
4077class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4078public:
4079 void SetUp() override {
4080 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004081 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004082 }
4083
4084 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4085 gui::DisplayInfo info;
4086 info.displayId = displayId;
4087 info.transform = transform;
4088 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004089 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004090 }
4091
4092 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4093 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004094 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004095 }
4096
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004097 void removeAllWindowsAndDisplays() {
4098 mDisplayInfos.clear();
4099 mWindowInfos.clear();
4100 }
4101
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004102 // Set up a test scenario where the display has a scaled projection and there are two windows
4103 // on the display.
4104 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4105 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4106 // respectively.
4107 ui::Transform displayTransform;
4108 displayTransform.set(2, 0, 0, 4);
4109 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4110
4111 std::shared_ptr<FakeApplicationHandle> application =
4112 std::make_shared<FakeApplicationHandle>();
4113
4114 // Add two windows to the display. Their frames are represented in the display space.
4115 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004116 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4117 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004118 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4119 addWindow(firstWindow);
4120
4121 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004122 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4123 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004124 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4125 addWindow(secondWindow);
4126 return {std::move(firstWindow), std::move(secondWindow)};
4127 }
4128
4129private:
4130 std::vector<gui::DisplayInfo> mDisplayInfos;
4131 std::vector<gui::WindowInfo> mWindowInfos;
4132};
4133
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004134TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004135 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4136 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004137 // selected so that if the hit test was performed with the point and the bounds being in
4138 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004139 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4140 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4141 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004142
4143 firstWindow->consumeMotionDown();
4144 secondWindow->assertNoEvents();
4145}
4146
4147// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4148// the event should be treated as being in the logical display space.
4149TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4150 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4151 // Send down to the first window. The point is represented in the logical display space. The
4152 // point is selected so that if the hit test was done in logical display space, then it would
4153 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004154 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004155 PointF{75 * 2, 55 * 4});
4156
4157 firstWindow->consumeMotionDown();
4158 secondWindow->assertNoEvents();
4159}
4160
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004161// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4162// event should be treated as being in the logical display space.
4163TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4164 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4165
4166 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4167 ui::Transform injectedEventTransform;
4168 injectedEventTransform.set(matrix);
4169 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4170 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4171
4172 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4173 .displayId(ADISPLAY_ID_DEFAULT)
4174 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004175 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004176 .x(untransformedPoint.x)
4177 .y(untransformedPoint.y))
4178 .build();
4179 event.transform(matrix);
4180
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004181 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004182 InputEventInjectionSync::WAIT_FOR_RESULT);
4183
4184 firstWindow->consumeMotionDown();
4185 secondWindow->assertNoEvents();
4186}
4187
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004188TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4189 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4190
4191 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004192 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4193 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4194 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004195
4196 firstWindow->assertNoEvents();
4197 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004198 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004199 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4200
4201 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4202 EXPECT_EQ(300, event->getRawX(0));
4203 EXPECT_EQ(880, event->getRawY(0));
4204
4205 // Ensure that the x and y values are in the window's coordinate space.
4206 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4207 // the logical display space. This will be the origin of the window space.
4208 EXPECT_EQ(100, event->getX(0));
4209 EXPECT_EQ(80, event->getY(0));
4210}
4211
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004212/** Ensure consistent behavior of InputDispatcher in all orientations. */
4213class InputDispatcherDisplayOrientationFixture
4214 : public InputDispatcherDisplayProjectionTest,
4215 public ::testing::WithParamInterface<ui::Rotation> {};
4216
4217// This test verifies the touchable region of a window for all rotations of the display by tapping
4218// in different locations on the display, specifically points close to the four corners of a
4219// window.
4220TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4221 constexpr static int32_t displayWidth = 400;
4222 constexpr static int32_t displayHeight = 800;
4223
4224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4225
4226 const auto rotation = GetParam();
4227
4228 // Set up the display with the specified rotation.
4229 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4230 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4231 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4232 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4233 logicalDisplayWidth, logicalDisplayHeight);
4234 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4235
4236 // Create a window with its bounds determined in the logical display.
4237 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4238 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4239 sp<FakeWindowHandle> window =
4240 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4241 window->setFrame(frameInDisplay, displayTransform);
4242 addWindow(window);
4243
4244 // The following points in logical display space should be inside the window.
4245 static const std::array<vec2, 4> insidePoints{
4246 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4247 for (const auto pointInsideWindow : insidePoints) {
4248 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4249 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004250 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4251 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4252 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004253 window->consumeMotionDown();
4254
Prabir Pradhan678438e2023-04-13 19:32:51 +00004255 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4256 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4257 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004258 window->consumeMotionUp();
4259 }
4260
4261 // The following points in logical display space should be outside the window.
4262 static const std::array<vec2, 5> outsidePoints{
4263 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4264 for (const auto pointOutsideWindow : outsidePoints) {
4265 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4266 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004267 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4268 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4269 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004270
Prabir Pradhan678438e2023-04-13 19:32:51 +00004271 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4272 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4273 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004274 }
4275 window->assertNoEvents();
4276}
4277
4278// Run the precision tests for all rotations.
4279INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4280 InputDispatcherDisplayOrientationFixture,
4281 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4282 ui::ROTATION_270),
4283 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4284 return ftl::enum_string(testParamInfo.param);
4285 });
4286
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004287using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4288 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004289
4290class TransferTouchFixture : public InputDispatcherTest,
4291 public ::testing::WithParamInterface<TransferFunction> {};
4292
4293TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004295
4296 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004297 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004298 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4299 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004300 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004301 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004302 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4303 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004304 sp<FakeWindowHandle> wallpaper =
4305 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4306 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004307 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004308 mDispatcher->onWindowInfosChanged(
4309 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004310
4311 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004312 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4313 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004314
Svet Ganov5d3bc372020-01-26 23:11:07 -08004315 // Only the first window should get the down event
4316 firstWindow->consumeMotionDown();
4317 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004318 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004319
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004320 // Transfer touch to the second window
4321 TransferFunction f = GetParam();
4322 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4323 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004324 // The first window gets cancel and the second gets down
4325 firstWindow->consumeMotionCancel();
4326 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004327 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004328
4329 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004330 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4331 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004332 // The first window gets no events and the second gets up
4333 firstWindow->assertNoEvents();
4334 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004335 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004336}
4337
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004338/**
4339 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4340 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4341 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4342 * natural to the user.
4343 * In this test, we are sending a pointer to both spy window and first window. We then try to
4344 * transfer touch to the second window. The dispatcher should identify the first window as the
4345 * one that should lose the gesture, and therefore the action should be to move the gesture from
4346 * the first window to the second.
4347 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4348 * the other API, as well.
4349 */
4350TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4352
4353 // Create a couple of windows + a spy window
4354 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004355 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004356 spyWindow->setTrustedOverlay(true);
4357 spyWindow->setSpy(true);
4358 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004359 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004360 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004361 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004362
4363 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004364 mDispatcher->onWindowInfosChanged(
4365 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004366
4367 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004368 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4369 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004370 // Only the first window and spy should get the down event
4371 spyWindow->consumeMotionDown();
4372 firstWindow->consumeMotionDown();
4373
4374 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4375 // if f === 'transferTouch'.
4376 TransferFunction f = GetParam();
4377 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4378 ASSERT_TRUE(success);
4379 // The first window gets cancel and the second gets down
4380 firstWindow->consumeMotionCancel();
4381 secondWindow->consumeMotionDown();
4382
4383 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004384 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4385 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004386 // The first window gets no events and the second+spy get up
4387 firstWindow->assertNoEvents();
4388 spyWindow->consumeMotionUp();
4389 secondWindow->consumeMotionUp();
4390}
4391
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004392TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004394
4395 PointF touchPoint = {10, 10};
4396
4397 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004398 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004399 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4400 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004401 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004402 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004403 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4404 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004405 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004406
4407 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004408 mDispatcher->onWindowInfosChanged(
4409 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004410
4411 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004412 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4413 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4414 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004415 // Only the first window should get the down event
4416 firstWindow->consumeMotionDown();
4417 secondWindow->assertNoEvents();
4418
4419 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004420 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4421 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004422 // Only the first window should get the pointer down event
4423 firstWindow->consumeMotionPointerDown(1);
4424 secondWindow->assertNoEvents();
4425
4426 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004427 TransferFunction f = GetParam();
4428 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4429 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004430 // The first window gets cancel and the second gets down and pointer down
4431 firstWindow->consumeMotionCancel();
4432 secondWindow->consumeMotionDown();
4433 secondWindow->consumeMotionPointerDown(1);
4434
4435 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004436 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4437 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004438 // The first window gets nothing and the second gets pointer up
4439 firstWindow->assertNoEvents();
4440 secondWindow->consumeMotionPointerUp(1);
4441
4442 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4444 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004445 // The first window gets nothing and the second gets up
4446 firstWindow->assertNoEvents();
4447 secondWindow->consumeMotionUp();
4448}
4449
Arthur Hungc539dbb2022-12-08 07:45:36 +00004450TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4452
4453 // Create a couple of windows
4454 sp<FakeWindowHandle> firstWindow =
4455 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4456 ADISPLAY_ID_DEFAULT);
4457 firstWindow->setDupTouchToWallpaper(true);
4458 sp<FakeWindowHandle> secondWindow =
4459 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4460 ADISPLAY_ID_DEFAULT);
4461 secondWindow->setDupTouchToWallpaper(true);
4462
4463 sp<FakeWindowHandle> wallpaper1 =
4464 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4465 wallpaper1->setIsWallpaper(true);
4466
4467 sp<FakeWindowHandle> wallpaper2 =
4468 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4469 wallpaper2->setIsWallpaper(true);
4470 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004471 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4472 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4473 {},
4474 0,
4475 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004476
4477 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004478 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4479 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004480
4481 // Only the first window should get the down event
4482 firstWindow->consumeMotionDown();
4483 secondWindow->assertNoEvents();
4484 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4485 wallpaper2->assertNoEvents();
4486
4487 // Transfer touch focus to the second window
4488 TransferFunction f = GetParam();
4489 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4490 ASSERT_TRUE(success);
4491
4492 // The first window gets cancel and the second gets down
4493 firstWindow->consumeMotionCancel();
4494 secondWindow->consumeMotionDown();
4495 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4496 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4497
4498 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004499 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4500 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004501 // The first window gets no events and the second gets up
4502 firstWindow->assertNoEvents();
4503 secondWindow->consumeMotionUp();
4504 wallpaper1->assertNoEvents();
4505 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4506}
4507
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004508// For the cases of single pointer touch and two pointers non-split touch, the api's
4509// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4510// for the case where there are multiple pointers split across several windows.
4511INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4512 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004513 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4514 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004515 return dispatcher->transferTouch(destChannelToken,
4516 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004517 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004518 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4519 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004520 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004521 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004522 }));
4523
Svet Ganov5d3bc372020-01-26 23:11:07 -08004524TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004526
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004527 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004528 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4529 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004530 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004531
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004532 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004533 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4534 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004535 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004536
4537 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004538 mDispatcher->onWindowInfosChanged(
4539 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004540
4541 PointF pointInFirst = {300, 200};
4542 PointF pointInSecond = {300, 600};
4543
4544 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4547 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004548 // Only the first window should get the down event
4549 firstWindow->consumeMotionDown();
4550 secondWindow->assertNoEvents();
4551
4552 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004553 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4554 ADISPLAY_ID_DEFAULT,
4555 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004556 // The first window gets a move and the second a down
4557 firstWindow->consumeMotionMove();
4558 secondWindow->consumeMotionDown();
4559
4560 // Transfer touch focus to the second window
4561 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4562 // The first window gets cancel and the new gets pointer down (it already saw down)
4563 firstWindow->consumeMotionCancel();
4564 secondWindow->consumeMotionPointerDown(1);
4565
4566 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004567 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4568 ADISPLAY_ID_DEFAULT,
4569 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004570 // The first window gets nothing and the second gets pointer up
4571 firstWindow->assertNoEvents();
4572 secondWindow->consumeMotionPointerUp(1);
4573
4574 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004575 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4576 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004577 // The first window gets nothing and the second gets up
4578 firstWindow->assertNoEvents();
4579 secondWindow->consumeMotionUp();
4580}
4581
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004582// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4583// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4584// touch is not supported, so the touch should continue on those windows and the transferred-to
4585// window should get nothing.
4586TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4587 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4588
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004589 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004590 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4591 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004592 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004593
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004594 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004595 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4596 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004597 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004598
4599 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004600 mDispatcher->onWindowInfosChanged(
4601 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004602
4603 PointF pointInFirst = {300, 200};
4604 PointF pointInSecond = {300, 600};
4605
4606 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004607 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4608 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4609 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004610 // Only the first window should get the down event
4611 firstWindow->consumeMotionDown();
4612 secondWindow->assertNoEvents();
4613
4614 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004615 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4616 ADISPLAY_ID_DEFAULT,
4617 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004618 // The first window gets a move and the second a down
4619 firstWindow->consumeMotionMove();
4620 secondWindow->consumeMotionDown();
4621
4622 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004623 const bool transferred =
4624 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004625 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4626 ASSERT_FALSE(transferred);
4627 firstWindow->assertNoEvents();
4628 secondWindow->assertNoEvents();
4629
4630 // The rest of the dispatch should proceed as normal
4631 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004632 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4633 ADISPLAY_ID_DEFAULT,
4634 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004635 // The first window gets MOVE and the second gets pointer up
4636 firstWindow->consumeMotionMove();
4637 secondWindow->consumeMotionUp();
4638
4639 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004640 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4641 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004642 // The first window gets nothing and the second gets up
4643 firstWindow->consumeMotionUp();
4644 secondWindow->assertNoEvents();
4645}
4646
Arthur Hungabbb9d82021-09-01 14:52:30 +00004647// This case will create two windows and one mirrored window on the default display and mirror
4648// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4649// the windows info of second display before default display.
4650TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4652 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004653 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004654 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004655 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004656 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004657 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004658
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004659 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004660 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004661
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004662 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004663 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004664
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004665 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004666 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004667
4668 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004669 mDispatcher->onWindowInfosChanged(
4670 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4671 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4672 *secondWindowInPrimary->getInfo()},
4673 {},
4674 0,
4675 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004676
4677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004678 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004679 {50, 50}))
4680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4681
4682 // Window should receive motion event.
4683 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4684
4685 // Transfer touch focus
4686 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4687 secondWindowInPrimary->getToken()));
4688 // The first window gets cancel.
4689 firstWindowInPrimary->consumeMotionCancel();
4690 secondWindowInPrimary->consumeMotionDown();
4691
4692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004693 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004694 ADISPLAY_ID_DEFAULT, {150, 50}))
4695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4696 firstWindowInPrimary->assertNoEvents();
4697 secondWindowInPrimary->consumeMotionMove();
4698
4699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004700 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004701 {150, 50}))
4702 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4703 firstWindowInPrimary->assertNoEvents();
4704 secondWindowInPrimary->consumeMotionUp();
4705}
4706
4707// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4708// 'transferTouch' api.
4709TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4711 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004712 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004713 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004714 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004715 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004716 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004717
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004718 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004719 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004720
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004721 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004722 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004723
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004724 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004725 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004726
4727 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004728 mDispatcher->onWindowInfosChanged(
4729 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
4730 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
4731 *secondWindowInPrimary->getInfo()},
4732 {},
4733 0,
4734 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00004735
4736 // Touch on second display.
4737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004738 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
4739 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00004740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4741
4742 // Window should receive motion event.
4743 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4744
4745 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004746 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004747
4748 // The first window gets cancel.
4749 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4750 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4751
4752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004753 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00004754 SECOND_DISPLAY_ID, {150, 50}))
4755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4756 firstWindowInPrimary->assertNoEvents();
4757 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4758
4759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004760 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00004761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4762 firstWindowInPrimary->assertNoEvents();
4763 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4764}
4765
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004766TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004768 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4769 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004770
Vishnu Nair47074b82020-08-14 11:54:47 -07004771 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004772 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004773 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004774
4775 window->consumeFocusEvent(true);
4776
Prabir Pradhan678438e2023-04-13 19:32:51 +00004777 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004778
4779 // Window should receive key down event.
4780 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004781
4782 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004783 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004784 mFakePolicy->assertUserActivityPoked();
4785}
4786
4787TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4789 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4790 "Fake Window", ADISPLAY_ID_DEFAULT);
4791
4792 window->setDisableUserActivity(true);
4793 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004794 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004795 setFocusedWindow(window);
4796
4797 window->consumeFocusEvent(true);
4798
4799 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4800
4801 // Window should receive key down event.
4802 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4803
4804 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004805 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004806 mFakePolicy->assertUserActivityNotPoked();
4807}
4808
4809TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4812 "Fake Window", ADISPLAY_ID_DEFAULT);
4813
4814 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004816 setFocusedWindow(window);
4817
4818 window->consumeFocusEvent(true);
4819
4820 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4821 mDispatcher->waitForIdle();
4822
4823 // System key is not passed down
4824 window->assertNoEvents();
4825
4826 // Should have poked user activity
4827 mFakePolicy->assertUserActivityPoked();
4828}
4829
4830TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4832 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4833 "Fake Window", ADISPLAY_ID_DEFAULT);
4834
4835 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004836 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004837 setFocusedWindow(window);
4838
4839 window->consumeFocusEvent(true);
4840
4841 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4842 mDispatcher->waitForIdle();
4843
4844 // System key is not passed down
4845 window->assertNoEvents();
4846
4847 // Should have poked user activity
4848 mFakePolicy->assertUserActivityPoked();
4849}
4850
4851TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4853 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4854 "Fake Window", ADISPLAY_ID_DEFAULT);
4855
4856 window->setDisableUserActivity(true);
4857 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004858 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00004859 setFocusedWindow(window);
4860
4861 window->consumeFocusEvent(true);
4862
4863 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4864 mDispatcher->waitForIdle();
4865
4866 // System key is not passed down
4867 window->assertNoEvents();
4868
4869 // Should have poked user activity
4870 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004871}
4872
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004873TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4875 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4876 "Fake Window", ADISPLAY_ID_DEFAULT);
4877
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004878 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004879
4880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004881 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004882 ADISPLAY_ID_DEFAULT, {100, 100}))
4883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4884
4885 window->consumeMotionEvent(
4886 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4887
4888 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004889 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004890 mFakePolicy->assertUserActivityPoked();
4891}
4892
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004893TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004895 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4896 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004899
Prabir Pradhan678438e2023-04-13 19:32:51 +00004900 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004901 mDispatcher->waitForIdle();
4902
4903 window->assertNoEvents();
4904}
4905
4906// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4907TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004909 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4910 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004911
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004912 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004913
4914 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004915 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004916 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004917 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4918 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004919
4920 // Window should receive only the motion event
4921 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4922 window->assertNoEvents(); // Key event or focus event will not be received
4923}
4924
arthurhungea3f4fc2020-12-21 23:18:53 +08004925TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4927
arthurhungea3f4fc2020-12-21 23:18:53 +08004928 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004929 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4930 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004931 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004932
arthurhungea3f4fc2020-12-21 23:18:53 +08004933 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004934 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4935 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004936 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004937
4938 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004939 mDispatcher->onWindowInfosChanged(
4940 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08004941
4942 PointF pointInFirst = {300, 200};
4943 PointF pointInSecond = {300, 600};
4944
4945 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004946 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4947 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4948 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004949 // Only the first window should get the down event
4950 firstWindow->consumeMotionDown();
4951 secondWindow->assertNoEvents();
4952
4953 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004954 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4955 ADISPLAY_ID_DEFAULT,
4956 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004957 // The first window gets a move and the second a down
4958 firstWindow->consumeMotionMove();
4959 secondWindow->consumeMotionDown();
4960
4961 // Send pointer cancel to the second window
4962 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004963 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004964 {pointInFirst, pointInSecond});
4965 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004966 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004967 // The first window gets move and the second gets cancel.
4968 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4969 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4970
4971 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004972 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4973 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004974 // The first window gets up and the second gets nothing.
4975 firstWindow->consumeMotionUp();
4976 secondWindow->assertNoEvents();
4977}
4978
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004979TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4981
4982 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004983 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004984 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004985 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4986 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4987 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4988
Harry Cutts33476232023-01-30 19:57:29 +00004989 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004990 window->assertNoEvents();
4991 mDispatcher->waitForIdle();
4992}
4993
chaviwd1c23182019-12-20 18:44:56 -08004994class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004995public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004996 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004997 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004998 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004999 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07005000 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00005001 }
5002
chaviwd1c23182019-12-20 18:44:56 -08005003 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
5004
5005 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005006 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
5007 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08005008 }
5009
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005010 std::optional<int32_t> receiveEvent() {
5011 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
5012 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005013
5014 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
5015
chaviwd1c23182019-12-20 18:44:56 -08005016 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005017 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08005018 expectedDisplayId, expectedFlags);
5019 }
5020
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005021 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005022 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005023 expectedDisplayId, expectedFlags);
5024 }
5025
chaviwd1c23182019-12-20 18:44:56 -08005026 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005027 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08005028 expectedDisplayId, expectedFlags);
5029 }
5030
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005031 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005032 mInputReceiver->consumeMotionEvent(
5033 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
5034 WithDisplayId(expectedDisplayId),
5035 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005036 }
5037
Arthur Hungfbfa5722021-11-16 02:45:54 +00005038 void consumeMotionPointerDown(int32_t pointerIdx) {
5039 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
5040 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005041 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005042 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00005043 }
5044
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005045 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
Evan Rosky84f07f02021-04-16 10:42:42 -07005046
chaviwd1c23182019-12-20 18:44:56 -08005047 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5048
5049private:
5050 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005051};
5052
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005053using InputDispatcherMonitorTest = InputDispatcherTest;
5054
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005055/**
5056 * Two entities that receive touch: A window, and a global monitor.
5057 * The touch goes to the window, and then the window disappears.
5058 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5059 * for the monitor, as well.
5060 * 1. foregroundWindow
5061 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5062 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005063TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5065 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005066 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005067
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005068 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005069
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005070 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005072 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005073 {100, 200}))
5074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5075
5076 // Both the foreground window and the global monitor should receive the touch down
5077 window->consumeMotionDown();
5078 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5079
5080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005081 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005082 ADISPLAY_ID_DEFAULT, {110, 200}))
5083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5084
5085 window->consumeMotionMove();
5086 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5087
5088 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005089 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005090 window->consumeMotionCancel();
5091 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5092
5093 // If more events come in, there will be no more foreground window to send them to. This will
5094 // cause a cancel for the monitor, as well.
5095 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005096 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005097 ADISPLAY_ID_DEFAULT, {120, 200}))
5098 << "Injection should fail because the window was removed";
5099 window->assertNoEvents();
5100 // Global monitor now gets the cancel
5101 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5102}
5103
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005104TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005105 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005106 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5107 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005108 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005109
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005110 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005111
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005113 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005115 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005116 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005117}
5118
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005119TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5120 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005121
Chris Yea209fde2020-07-22 13:54:51 -07005122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005123 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5124 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005125 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005126
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005128 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005130 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005131 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005132
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005133 // Pilfer pointers from the monitor.
5134 // This should not do anything and the window should continue to receive events.
5135 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005136
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005138 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005139 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005141
5142 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5143 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005144}
5145
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005146TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005148 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5149 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005150 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005151 window->setWindowOffset(20, 40);
5152 window->setWindowTransform(0, 1, -1, 0);
5153
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005154 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005155
5156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005157 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5159 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5160 MotionEvent* event = monitor.consumeMotion();
5161 // Even though window has transform, gesture monitor must not.
5162 ASSERT_EQ(ui::Transform(), event->getTransform());
5163}
5164
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005165TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005167 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005168
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005169 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005170 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005171 << "Injection should fail if there is a monitor, but no touchable window";
5172 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005173}
5174
chaviw81e2bb92019-12-18 15:03:51 -08005175TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005177 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5178 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005179
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005181
5182 NotifyMotionArgs motionArgs =
5183 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5184 ADISPLAY_ID_DEFAULT);
5185
Prabir Pradhan678438e2023-04-13 19:32:51 +00005186 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005187 // Window should receive motion down event.
5188 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5189
5190 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005191 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005192 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5193 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5194 motionArgs.pointerCoords[0].getX() - 10);
5195
Prabir Pradhan678438e2023-04-13 19:32:51 +00005196 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005197 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005198 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005199}
5200
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005201/**
5202 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5203 * the device default right away. In the test scenario, we check both the default value,
5204 * and the action of enabling / disabling.
5205 */
5206TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005208 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5209 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005210 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005211
5212 // Set focused application.
5213 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005214 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005215
5216 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005217 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005218 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005219 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005220
5221 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005222 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005223 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005224 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005225
5226 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005227 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005228 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005229 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005230 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005231 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005232 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005233 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005234
5235 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005236 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005237 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005238 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005239
5240 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005241 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005242 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005243 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005244 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005246 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005247 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005248
5249 window->assertNoEvents();
5250}
5251
Gang Wange9087892020-01-07 12:17:14 -05005252TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005253 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005254 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5255 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005256
5257 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005258 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005259
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005260 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005261 setFocusedWindow(window);
5262
Harry Cutts33476232023-01-30 19:57:29 +00005263 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005264
Prabir Pradhan678438e2023-04-13 19:32:51 +00005265 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5266 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005267
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005268 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005269 ASSERT_NE(event, nullptr);
5270
5271 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5272 ASSERT_NE(verified, nullptr);
5273 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5274
5275 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5276 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5277 ASSERT_EQ(keyArgs.source, verified->source);
5278 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5279
5280 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5281
5282 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005283 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005284 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005285 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5286 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5287 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5288 ASSERT_EQ(0, verifiedKey.repeatCount);
5289}
5290
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005291TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005293 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5294 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005295
5296 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5297
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005298 ui::Transform transform;
5299 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5300
5301 gui::DisplayInfo displayInfo;
5302 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5303 displayInfo.transform = transform;
5304
Patrick Williamsd828f302023-04-28 17:52:08 -05005305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005306
Prabir Pradhan678438e2023-04-13 19:32:51 +00005307 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005308 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5309 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005310 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005311
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005312 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005313 ASSERT_NE(event, nullptr);
5314
5315 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5316 ASSERT_NE(verified, nullptr);
5317 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5318
5319 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5320 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5321 EXPECT_EQ(motionArgs.source, verified->source);
5322 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5323
5324 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5325
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005326 const vec2 rawXY =
5327 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5328 motionArgs.pointerCoords[0].getXYValue());
5329 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5330 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005331 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005332 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005333 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005334 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5335 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5336}
5337
chaviw09c8d2d2020-08-24 15:48:26 -07005338/**
5339 * Ensure that separate calls to sign the same data are generating the same key.
5340 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5341 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5342 * tests.
5343 */
5344TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5345 KeyEvent event = getTestKeyEvent();
5346 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5347
5348 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5349 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5350 ASSERT_EQ(hmac1, hmac2);
5351}
5352
5353/**
5354 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5355 */
5356TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5357 KeyEvent event = getTestKeyEvent();
5358 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5359 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5360
5361 verifiedEvent.deviceId += 1;
5362 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5363
5364 verifiedEvent.source += 1;
5365 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5366
5367 verifiedEvent.eventTimeNanos += 1;
5368 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5369
5370 verifiedEvent.displayId += 1;
5371 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5372
5373 verifiedEvent.action += 1;
5374 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5375
5376 verifiedEvent.downTimeNanos += 1;
5377 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5378
5379 verifiedEvent.flags += 1;
5380 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5381
5382 verifiedEvent.keyCode += 1;
5383 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5384
5385 verifiedEvent.scanCode += 1;
5386 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5387
5388 verifiedEvent.metaState += 1;
5389 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5390
5391 verifiedEvent.repeatCount += 1;
5392 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5393}
5394
Vishnu Nair958da932020-08-21 17:12:37 -07005395TEST_F(InputDispatcherTest, SetFocusedWindow) {
5396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5397 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005398 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005399 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005400 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005401 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5402
5403 // Top window is also focusable but is not granted focus.
5404 windowTop->setFocusable(true);
5405 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005406 mDispatcher->onWindowInfosChanged(
5407 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005408 setFocusedWindow(windowSecond);
5409
5410 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005412 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005413
5414 // Focused window should receive event.
5415 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5416 windowTop->assertNoEvents();
5417}
5418
5419TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5421 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005422 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005423 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5424
5425 window->setFocusable(true);
5426 // Release channel for window is no longer valid.
5427 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005428 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005429 setFocusedWindow(window);
5430
5431 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005432 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005433
5434 // window channel is invalid, so it should not receive any input event.
5435 window->assertNoEvents();
5436}
5437
5438TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5440 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005441 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005442 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005443 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5444
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005445 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005446 setFocusedWindow(window);
5447
5448 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005449 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005450
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005451 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005452 window->assertNoEvents();
5453}
5454
5455TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5457 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005458 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005459 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005460 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005461 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5462
5463 windowTop->setFocusable(true);
5464 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005465 mDispatcher->onWindowInfosChanged(
5466 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005467 setFocusedWindow(windowTop);
5468 windowTop->consumeFocusEvent(true);
5469
Chavi Weingarten847e8512023-03-29 00:26:09 +00005470 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005471 mDispatcher->onWindowInfosChanged(
5472 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005473 windowSecond->consumeFocusEvent(true);
5474 windowTop->consumeFocusEvent(false);
5475
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005477 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005478
5479 // Focused window should receive event.
5480 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5481}
5482
Chavi Weingarten847e8512023-03-29 00:26:09 +00005483TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5485 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005486 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005487 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005488 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005489 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5490
5491 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005492 windowSecond->setFocusable(false);
5493 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005494 mDispatcher->onWindowInfosChanged(
5495 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005496 setFocusedWindow(windowTop);
5497 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005498
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005499 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005500 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005501
5502 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005503 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005504 windowSecond->assertNoEvents();
5505}
5506
5507TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5509 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005510 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005511 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005512 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5513 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005514 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5515
5516 window->setFocusable(true);
5517 previousFocusedWindow->setFocusable(true);
5518 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005519 mDispatcher->onWindowInfosChanged(
5520 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005521 setFocusedWindow(previousFocusedWindow);
5522 previousFocusedWindow->consumeFocusEvent(true);
5523
5524 // Requesting focus on invisible window takes focus from currently focused window.
5525 setFocusedWindow(window);
5526 previousFocusedWindow->consumeFocusEvent(false);
5527
5528 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005530 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5531 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005532
5533 // Window does not get focus event or key down.
5534 window->assertNoEvents();
5535
5536 // Window becomes visible.
5537 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005538 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005539
5540 // Window receives focus event.
5541 window->consumeFocusEvent(true);
5542 // Focused window receives key down.
5543 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5544}
5545
Vishnu Nair599f1412021-06-21 10:39:58 -07005546TEST_F(InputDispatcherTest, DisplayRemoved) {
5547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5548 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005549 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005550 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5551
5552 // window is granted focus.
5553 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005555 setFocusedWindow(window);
5556 window->consumeFocusEvent(true);
5557
5558 // When a display is removed window loses focus.
5559 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5560 window->consumeFocusEvent(false);
5561}
5562
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005563/**
5564 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5565 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5566 * of the 'slipperyEnterWindow'.
5567 *
5568 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5569 * a way so that the touched location is no longer covered by the top window.
5570 *
5571 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5572 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5573 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5574 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5575 * with ACTION_DOWN).
5576 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5577 * window moved itself away from the touched location and had Flag::SLIPPERY.
5578 *
5579 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5580 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5581 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5582 *
5583 * In this test, we ensure that the event received by the bottom window has
5584 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5585 */
5586TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005587 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005588 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005589
5590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5591 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5592
5593 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005594 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005595 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005596 // Make sure this one overlaps the bottom window
5597 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5598 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5599 // one. Windows with the same owner are not considered to be occluding each other.
5600 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5601
5602 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005603 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005604 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5605
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005606 mDispatcher->onWindowInfosChanged(
5607 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005608
5609 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005610 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5611 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5612 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005613 slipperyExitWindow->consumeMotionDown();
5614 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005615 mDispatcher->onWindowInfosChanged(
5616 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005617
Prabir Pradhan678438e2023-04-13 19:32:51 +00005618 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5619 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5620 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005621
5622 slipperyExitWindow->consumeMotionCancel();
5623
5624 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5625 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5626}
5627
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005628/**
5629 * Two windows, one on the left and another on the right. The left window is slippery. The right
5630 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5631 * touch moves from the left window into the right window, the gesture should continue to go to the
5632 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5633 * reproduces a crash.
5634 */
5635TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5637
5638 sp<FakeWindowHandle> leftSlipperyWindow =
5639 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5640 leftSlipperyWindow->setSlippery(true);
5641 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5642
5643 sp<FakeWindowHandle> rightDropTouchesWindow =
5644 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5645 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5646 rightDropTouchesWindow->setDropInput(true);
5647
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005648 mDispatcher->onWindowInfosChanged(
5649 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005650
5651 // Start touch in the left window
5652 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5653 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5654 .build());
5655 leftSlipperyWindow->consumeMotionDown();
5656
5657 // And move it into the right window
5658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5659 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5660 .build());
5661
5662 // Since the right window isn't eligible to receive input, touch does not slip.
5663 // The left window continues to receive the gesture.
5664 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5665 rightDropTouchesWindow->assertNoEvents();
5666}
5667
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005668TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005669 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5671
5672 sp<FakeWindowHandle> leftWindow =
5673 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5674 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005675 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005676
5677 sp<FakeWindowHandle> rightSpy =
5678 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5679 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005680 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005681 rightSpy->setSpy(true);
5682 rightSpy->setTrustedOverlay(true);
5683
5684 sp<FakeWindowHandle> rightWindow =
5685 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5686 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005687 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005689 mDispatcher->onWindowInfosChanged(
5690 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005691
5692 // Touch in the left window
5693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5694 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5695 .build());
5696 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5697 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005698 ASSERT_NO_FATAL_FAILURE(
5699 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005700
5701 // Touch another finger over the right windows
5702 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5703 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5704 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5705 .build());
5706 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5707 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5708 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5709 mDispatcher->waitForIdle();
5710 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005711 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5712 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005713
5714 // Release finger over left window. The UP actions are not treated as device interaction.
5715 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5716 // is part of the UP action, we do not treat this as device interaction.
5717 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5718 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5719 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5720 .build());
5721 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5722 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5723 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5724 mDispatcher->waitForIdle();
5725 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5726
5727 // Move remaining finger
5728 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5729 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5730 .build());
5731 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5732 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5733 mDispatcher->waitForIdle();
5734 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005735 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005736
5737 // Release all fingers
5738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5739 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5740 .build());
5741 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5742 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5743 mDispatcher->waitForIdle();
5744 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5745}
5746
5747TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5749
5750 sp<FakeWindowHandle> window =
5751 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5752 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005753 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005756 setFocusedWindow(window);
5757 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5758
5759 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5760 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5761 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005762 ASSERT_NO_FATAL_FAILURE(
5763 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005764
5765 // The UP actions are not treated as device interaction.
5766 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5767 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5768 mDispatcher->waitForIdle();
5769 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5770}
5771
Garfield Tan1c7bc862020-01-28 13:24:04 -08005772class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5773protected:
5774 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5775 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5776
Chris Yea209fde2020-07-22 13:54:51 -07005777 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005778 sp<FakeWindowHandle> mWindow;
5779
5780 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005781 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005782 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005783 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005784 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005785 ASSERT_EQ(OK, mDispatcher->start());
5786
5787 setUpWindow();
5788 }
5789
5790 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005791 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005792 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005793
Vishnu Nair47074b82020-08-14 11:54:47 -07005794 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005795 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005796 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005797 mWindow->consumeFocusEvent(true);
5798 }
5799
Chris Ye2ad95392020-09-01 13:44:44 -07005800 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005801 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005802 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005803 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005804 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005805
5806 // Window should receive key down event.
5807 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5808 }
5809
5810 void expectKeyRepeatOnce(int32_t repeatCount) {
5811 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005812 mWindow->consumeKeyEvent(
5813 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08005814 }
5815
Chris Ye2ad95392020-09-01 13:44:44 -07005816 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005817 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005818 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005819 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005820 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005821
5822 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005823 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005824 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005825 }
5826};
5827
5828TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005829 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005830 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5831 expectKeyRepeatOnce(repeatCount);
5832 }
5833}
5834
5835TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005836 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005837 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5838 expectKeyRepeatOnce(repeatCount);
5839 }
Harry Cutts33476232023-01-30 19:57:29 +00005840 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005841 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005842 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5843 expectKeyRepeatOnce(repeatCount);
5844 }
5845}
5846
5847TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005848 sendAndConsumeKeyDown(/*deviceId=*/1);
5849 expectKeyRepeatOnce(/*repeatCount=*/1);
5850 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005851 mWindow->assertNoEvents();
5852}
5853
5854TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005855 sendAndConsumeKeyDown(/*deviceId=*/1);
5856 expectKeyRepeatOnce(/*repeatCount=*/1);
5857 sendAndConsumeKeyDown(/*deviceId=*/2);
5858 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005859 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005860 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005861 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005862 expectKeyRepeatOnce(/*repeatCount=*/2);
5863 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005864 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005865 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005866 mWindow->assertNoEvents();
5867}
5868
5869TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005870 sendAndConsumeKeyDown(/*deviceId=*/1);
5871 expectKeyRepeatOnce(/*repeatCount=*/1);
5872 sendAndConsumeKeyDown(/*deviceId=*/2);
5873 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005874 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005875 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005876 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005877 mWindow->assertNoEvents();
5878}
5879
liushenxiang42232912021-05-21 20:24:09 +08005880TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5881 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005882 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005883 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005884 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5885 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5886 mWindow->assertNoEvents();
5887}
5888
Garfield Tan1c7bc862020-01-28 13:24:04 -08005889TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005890 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005891 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005892 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005893 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005894 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5895 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5896 IdGenerator::getSource(repeatEvent->getId()));
5897 }
5898}
5899
5900TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005901 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005902 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005903
5904 std::unordered_set<int32_t> idSet;
5905 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005906 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005907 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5908 int32_t id = repeatEvent->getId();
5909 EXPECT_EQ(idSet.end(), idSet.find(id));
5910 idSet.insert(id);
5911 }
5912}
5913
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005914/* Test InputDispatcher for MultiDisplay */
5915class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5916public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005917 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005918 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005919
Chris Yea209fde2020-07-22 13:54:51 -07005920 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005921 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005922 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005923
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005924 // Set focus window for primary display, but focused display would be second one.
5925 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005926 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005927 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
5928
Vishnu Nair958da932020-08-21 17:12:37 -07005929 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005930 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005931
Chris Yea209fde2020-07-22 13:54:51 -07005932 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005933 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005934 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005935 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005936 // Set focus display to second one.
5937 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5938 // Set focus window for second display.
5939 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005940 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005941 mDispatcher->onWindowInfosChanged(
5942 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005943 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005944 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005945 }
5946
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005947 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005948 InputDispatcherTest::TearDown();
5949
Chris Yea209fde2020-07-22 13:54:51 -07005950 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005951 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005952 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005953 windowInSecondary.clear();
5954 }
5955
5956protected:
Chris Yea209fde2020-07-22 13:54:51 -07005957 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005958 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005959 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005960 sp<FakeWindowHandle> windowInSecondary;
5961};
5962
5963TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5964 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005966 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005968 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005969 windowInSecondary->assertNoEvents();
5970
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005971 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005973 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005975 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005976 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005977}
5978
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005979TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005980 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005982 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005983 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005984 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005985 windowInSecondary->assertNoEvents();
5986
5987 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005989 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005990 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005991 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005992
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005993 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005994 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08005995
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005996 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005997 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005998 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005999
6000 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006001 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006002 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006003 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006004 windowInSecondary->assertNoEvents();
6005}
6006
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006007// Test per-display input monitors for motion event.
6008TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006009 FakeMonitorReceiver monitorInPrimary =
6010 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6011 FakeMonitorReceiver monitorInSecondary =
6012 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006013
6014 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006016 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006018 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006019 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006020 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006021 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006022
6023 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006025 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006027 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006028 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006029 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006030 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006031
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006032 // Lift up the touch from the second display
6033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006034 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6036 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6037 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6038
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006039 // Test inject a non-pointer motion event.
6040 // If specific a display, it will dispatch to the focused window of particular display,
6041 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006043 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006045 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006046 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006047 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006048 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006049}
6050
6051// Test per-display input monitors for key event.
6052TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006053 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006054 FakeMonitorReceiver monitorInPrimary =
6055 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6056 FakeMonitorReceiver monitorInSecondary =
6057 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006058
6059 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006061 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006062 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006063 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006064 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006065 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006066}
6067
Vishnu Nair958da932020-08-21 17:12:37 -07006068TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6069 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006070 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006071 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006072 mDispatcher->onWindowInfosChanged(
6073 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6074 *windowInSecondary->getInfo()},
6075 {},
6076 0,
6077 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006078 setFocusedWindow(secondWindowInPrimary);
6079 windowInPrimary->consumeFocusEvent(false);
6080 secondWindowInPrimary->consumeFocusEvent(true);
6081
6082 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6084 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006085 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006086 windowInPrimary->assertNoEvents();
6087 windowInSecondary->assertNoEvents();
6088 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6089}
6090
Arthur Hungdfd528e2021-12-08 13:23:04 +00006091TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6092 FakeMonitorReceiver monitorInPrimary =
6093 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6094 FakeMonitorReceiver monitorInSecondary =
6095 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6096
6097 // Test touch down on primary display.
6098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006099 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6101 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6102 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6103
6104 // Test touch down on second display.
6105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006106 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6108 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6109 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6110
6111 // Trigger cancel touch.
6112 mDispatcher->cancelCurrentTouch();
6113 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6114 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6115 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6116 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6117
6118 // Test inject a move motion event, no window/monitor should receive the event.
6119 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006120 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006121 ADISPLAY_ID_DEFAULT, {110, 200}))
6122 << "Inject motion event should return InputEventInjectionResult::FAILED";
6123 windowInPrimary->assertNoEvents();
6124 monitorInPrimary.assertNoEvents();
6125
6126 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006127 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006128 SECOND_DISPLAY_ID, {110, 200}))
6129 << "Inject motion event should return InputEventInjectionResult::FAILED";
6130 windowInSecondary->assertNoEvents();
6131 monitorInSecondary.assertNoEvents();
6132}
6133
Jackal Guof9696682018-10-05 12:23:23 +08006134class InputFilterTest : public InputDispatcherTest {
6135protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006136 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6137 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006138 NotifyMotionArgs motionArgs;
6139
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006140 motionArgs =
6141 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006142 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006143 motionArgs =
6144 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006145 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006146 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006147 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006148 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006149 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006150 } else {
6151 mFakePolicy->assertFilterInputEventWasNotCalled();
6152 }
6153 }
6154
6155 void testNotifyKey(bool expectToBeFiltered) {
6156 NotifyKeyArgs keyArgs;
6157
6158 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006159 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006160 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006161 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006162 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006163
6164 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006165 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006166 } else {
6167 mFakePolicy->assertFilterInputEventWasNotCalled();
6168 }
6169 }
6170};
6171
6172// Test InputFilter for MotionEvent
6173TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6174 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006175 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6176 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006177
6178 // Enable InputFilter
6179 mDispatcher->setInputFilterEnabled(true);
6180 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006181 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6182 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006183
6184 // Disable InputFilter
6185 mDispatcher->setInputFilterEnabled(false);
6186 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006187 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6188 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006189}
6190
6191// Test InputFilter for KeyEvent
6192TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6193 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006194 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006195
6196 // Enable InputFilter
6197 mDispatcher->setInputFilterEnabled(true);
6198 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006199 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006200
6201 // Disable InputFilter
6202 mDispatcher->setInputFilterEnabled(false);
6203 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006204 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006205}
6206
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006207// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6208// logical display coordinate space.
6209TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6210 ui::Transform firstDisplayTransform;
6211 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6212 ui::Transform secondDisplayTransform;
6213 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6214
6215 std::vector<gui::DisplayInfo> displayInfos(2);
6216 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6217 displayInfos[0].transform = firstDisplayTransform;
6218 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6219 displayInfos[1].transform = secondDisplayTransform;
6220
Patrick Williamsd828f302023-04-28 17:52:08 -05006221 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006222
6223 // Enable InputFilter
6224 mDispatcher->setInputFilterEnabled(true);
6225
6226 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006227 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6228 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006229}
6230
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006231class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6232protected:
6233 virtual void SetUp() override {
6234 InputDispatcherTest::SetUp();
6235
6236 /**
6237 * We don't need to enable input filter to test the injected event policy, but we enabled it
6238 * here to make the tests more realistic, since this policy only matters when inputfilter is
6239 * on.
6240 */
6241 mDispatcher->setInputFilterEnabled(true);
6242
6243 std::shared_ptr<InputApplicationHandle> application =
6244 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006245 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6246 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006247
6248 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6249 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006250 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006251 setFocusedWindow(mWindow);
6252 mWindow->consumeFocusEvent(true);
6253 }
6254
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006255 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6256 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006257 KeyEvent event;
6258
6259 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6260 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6261 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006262 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006263 const int32_t additionalPolicyFlags =
6264 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006266 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006267 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006268 policyFlags | additionalPolicyFlags));
6269
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006270 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006271 }
6272
6273 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6274 int32_t flags) {
6275 MotionEvent event;
6276 PointerProperties pointerProperties[1];
6277 PointerCoords pointerCoords[1];
6278 pointerProperties[0].clear();
6279 pointerProperties[0].id = 0;
6280 pointerCoords[0].clear();
6281 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6282 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6283
6284 ui::Transform identityTransform;
6285 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6286 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6287 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6288 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6289 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006290 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006291 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006292 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006293
6294 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006296 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006297 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006298 policyFlags | additionalPolicyFlags));
6299
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006300 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006301 }
6302
6303private:
6304 sp<FakeWindowHandle> mWindow;
6305};
6306
6307TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006308 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6309 // filter. Without it, the event will no different from a regularly injected event, and the
6310 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006311 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6312 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006313}
6314
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006315TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006316 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006317 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006318 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6319}
6320
6321TEST_F(InputFilterInjectionPolicyTest,
6322 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6323 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006324 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006325 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006326}
6327
6328TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006329 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6330 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006331}
6332
chaviwfd6d3512019-03-25 13:23:49 -07006333class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006334 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006335 InputDispatcherTest::SetUp();
6336
Chris Yea209fde2020-07-22 13:54:51 -07006337 std::shared_ptr<FakeApplicationHandle> application =
6338 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006339 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006340 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006341 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006342
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006343 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006344 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006345 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006346
6347 // Set focused application.
6348 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006349 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006350
6351 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006352 mDispatcher->onWindowInfosChanged(
6353 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006354 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006355 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006356 }
6357
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006358 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006359 InputDispatcherTest::TearDown();
6360
6361 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006362 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006363 }
6364
6365protected:
6366 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006367 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006368 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006369};
6370
6371// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6372// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6373// the onPointerDownOutsideFocus callback.
6374TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006376 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006377 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006379 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006380
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006381 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006382 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6383}
6384
6385// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6386// DOWN on the window that doesn't have focus. Ensure no window received the
6387// onPointerDownOutsideFocus callback.
6388TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006390 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6391 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006392 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006393 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006394
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006395 ASSERT_TRUE(mDispatcher->waitForIdle());
6396 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006397}
6398
6399// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6400// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6401TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006403 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006404 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006405 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006406
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006407 ASSERT_TRUE(mDispatcher->waitForIdle());
6408 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006409}
6410
6411// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6412// DOWN on the window that already has focus. Ensure no window received the
6413// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006414TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006416 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006417 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006419 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006420
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006421 ASSERT_TRUE(mDispatcher->waitForIdle());
6422 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006423}
6424
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006425// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6426// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6427TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6428 const MotionEvent event =
6429 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6430 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006431 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006432 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6433 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6436 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6437
6438 ASSERT_TRUE(mDispatcher->waitForIdle());
6439 mFakePolicy->assertOnPointerDownWasNotCalled();
6440 // Ensure that the unfocused window did not receive any FOCUS events.
6441 mUnfocusedWindow->assertNoEvents();
6442}
6443
chaviwaf87b3e2019-10-01 16:59:28 -07006444// These tests ensures we can send touch events to a single client when there are multiple input
6445// windows that point to the same client token.
6446class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6447 virtual void SetUp() override {
6448 InputDispatcherTest::SetUp();
6449
Chris Yea209fde2020-07-22 13:54:51 -07006450 std::shared_ptr<FakeApplicationHandle> application =
6451 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006452 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6453 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006454 mWindow1->setFrame(Rect(0, 0, 100, 100));
6455
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006456 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6457 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006458 mWindow2->setFrame(Rect(100, 100, 200, 200));
6459
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006460 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006461 }
6462
6463protected:
6464 sp<FakeWindowHandle> mWindow1;
6465 sp<FakeWindowHandle> mWindow2;
6466
6467 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006468 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006469 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6470 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006471 }
6472
6473 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6474 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006475 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006476 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006477
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006478 ASSERT_NE(nullptr, motionEvent)
6479 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006480
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006481 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006482 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006483
6484 for (size_t i = 0; i < points.size(); i++) {
6485 float expectedX = points[i].x;
6486 float expectedY = points[i].y;
6487
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006488 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006489 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006490 << ", got " << motionEvent->getX(i);
6491 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006492 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006493 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006494 }
6495 }
chaviw9eaa22c2020-07-01 16:21:27 -07006496
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006497 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006498 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006499 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6500 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006501
6502 // Always consume from window1 since it's the window that has the InputReceiver
6503 consumeMotionEvent(mWindow1, action, expectedPoints);
6504 }
chaviwaf87b3e2019-10-01 16:59:28 -07006505};
6506
6507TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6508 // Touch Window 1
6509 PointF touchedPoint = {10, 10};
6510 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006511 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006512
6513 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006514 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006515
6516 // Touch Window 2
6517 touchedPoint = {150, 150};
6518 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006519 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006520}
6521
chaviw9eaa22c2020-07-01 16:21:27 -07006522TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6523 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006524 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006525 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006526
6527 // Touch Window 1
6528 PointF touchedPoint = {10, 10};
6529 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006530 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006531 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006532 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006533
6534 // Touch Window 2
6535 touchedPoint = {150, 150};
6536 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006537 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6538 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006539
chaviw9eaa22c2020-07-01 16:21:27 -07006540 // Update the transform so rotation is set
6541 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006542 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006543 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6544 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006545}
6546
chaviw9eaa22c2020-07-01 16:21:27 -07006547TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006548 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006549 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006550
6551 // Touch Window 1
6552 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6553 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006554 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006555
6556 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006557 touchedPoints.push_back(PointF{150, 150});
6558 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006559 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006560
chaviw9eaa22c2020-07-01 16:21:27 -07006561 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006562 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006563 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006564
chaviw9eaa22c2020-07-01 16:21:27 -07006565 // Update the transform so rotation is set for Window 2
6566 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006567 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006568 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006569 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006570}
6571
chaviw9eaa22c2020-07-01 16:21:27 -07006572TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006573 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006574 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006575
6576 // Touch Window 1
6577 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6578 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006579 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006580
6581 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006582 touchedPoints.push_back(PointF{150, 150});
6583 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006584
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006585 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006586
6587 // Move both windows
6588 touchedPoints = {{20, 20}, {175, 175}};
6589 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6590 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6591
chaviw9eaa22c2020-07-01 16:21:27 -07006592 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006593
chaviw9eaa22c2020-07-01 16:21:27 -07006594 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006595 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006596 expectedPoints.pop_back();
6597
6598 // Touch Window 2
6599 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006600 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006601 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006602 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006603
6604 // Move both windows
6605 touchedPoints = {{20, 20}, {175, 175}};
6606 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6607 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6608
6609 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006610}
6611
6612TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6613 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006614 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006615
6616 // Touch Window 1
6617 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6618 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006619 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006620
6621 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006622 touchedPoints.push_back(PointF{150, 150});
6623 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006624
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006625 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006626
6627 // Move both windows
6628 touchedPoints = {{20, 20}, {175, 175}};
6629 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6630 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6631
chaviw9eaa22c2020-07-01 16:21:27 -07006632 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006633}
6634
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006635/**
6636 * When one of the windows is slippery, the touch should not slip into the other window with the
6637 * same input channel.
6638 */
6639TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6640 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006641 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006642
6643 // Touch down in window 1
6644 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6645 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6646 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6647
6648 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6649 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6650 // getting generated.
6651 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6652 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6653
6654 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6655}
6656
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006657/**
6658 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6659 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6660 * that the pointer is hovering over may have a different transform.
6661 */
6662TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006663 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006664
6665 // Start hover in window 1
6666 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6667 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6668 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6669 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6670
6671 // Move hover to window 2.
6672 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6673 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6674
6675 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6676 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6677 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6678}
6679
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006680class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6681 virtual void SetUp() override {
6682 InputDispatcherTest::SetUp();
6683
Chris Yea209fde2020-07-22 13:54:51 -07006684 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006685 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006686 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6687 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006688 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006689 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006690 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006691
6692 // Set focused application.
6693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6694
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006695 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006696 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006697 mWindow->consumeFocusEvent(true);
6698 }
6699
6700 virtual void TearDown() override {
6701 InputDispatcherTest::TearDown();
6702 mWindow.clear();
6703 }
6704
6705protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006706 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07006707 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006708 sp<FakeWindowHandle> mWindow;
6709 static constexpr PointF WINDOW_LOCATION = {20, 20};
6710
6711 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006713 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006714 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006716 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006717 WINDOW_LOCATION));
6718 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006719
6720 sp<FakeWindowHandle> addSpyWindow() {
6721 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006722 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006723 spy->setTrustedOverlay(true);
6724 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006725 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006726 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006727 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006728 return spy;
6729 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006730};
6731
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006732// Send a tap and respond, which should not cause an ANR.
6733TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6734 tapOnWindow();
6735 mWindow->consumeMotionDown();
6736 mWindow->consumeMotionUp();
6737 ASSERT_TRUE(mDispatcher->waitForIdle());
6738 mFakePolicy->assertNotifyAnrWasNotCalled();
6739}
6740
6741// Send a regular key and respond, which should not cause an ANR.
6742TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006744 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6745 ASSERT_TRUE(mDispatcher->waitForIdle());
6746 mFakePolicy->assertNotifyAnrWasNotCalled();
6747}
6748
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006749TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6750 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006751 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006752 mWindow->consumeFocusEvent(false);
6753
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006754 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006755 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6756 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00006757 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006759 // Key will not go to window because we have no focused window.
6760 // The 'no focused window' ANR timer should start instead.
6761
6762 // Now, the focused application goes away.
6763 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6764 // The key should get dropped and there should be no ANR.
6765
6766 ASSERT_TRUE(mDispatcher->waitForIdle());
6767 mFakePolicy->assertNotifyAnrWasNotCalled();
6768}
6769
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006770// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006771// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6772// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006773TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006776 WINDOW_LOCATION));
6777
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006778 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6779 ASSERT_TRUE(sequenceNum);
6780 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006781 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006782
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006783 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006784 mWindow->consumeMotionEvent(
6785 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006786 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006787 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006788}
6789
6790// Send a key to the app and have the app not respond right away.
6791TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6792 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006794 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6795 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006796 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006797 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006798 ASSERT_TRUE(mDispatcher->waitForIdle());
6799}
6800
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006801// We have a focused application, but no focused window
6802TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006803 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006804 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006805 mWindow->consumeFocusEvent(false);
6806
6807 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006809 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006810 WINDOW_LOCATION));
6811 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6812 mDispatcher->waitForIdle();
6813 mFakePolicy->assertNotifyAnrWasNotCalled();
6814
6815 // Once a focused event arrives, we get an ANR for this application
6816 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6817 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006818 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006819 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006820 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006821 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006822 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006823 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006824 ASSERT_TRUE(mDispatcher->waitForIdle());
6825}
6826
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006827/**
6828 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6829 * there will not be an ANR.
6830 */
6831TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6832 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006833 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006834 mWindow->consumeFocusEvent(false);
6835
6836 KeyEvent event;
6837 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6838 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6839
6840 // Define a valid key down event that is stale (too old).
6841 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006842 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006843 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006844
6845 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6846
6847 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006848 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006849 InputEventInjectionSync::WAIT_FOR_RESULT,
6850 INJECT_EVENT_TIMEOUT, policyFlags);
6851 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6852 << "Injection should fail because the event is stale";
6853
6854 ASSERT_TRUE(mDispatcher->waitForIdle());
6855 mFakePolicy->assertNotifyAnrWasNotCalled();
6856 mWindow->assertNoEvents();
6857}
6858
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006859// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006860// Make sure that we don't notify policy twice about the same ANR.
6861TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07006862 const std::chrono::duration appTimeout = 400ms;
6863 mApplication->setDispatchingTimeout(appTimeout);
6864 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6865
Vishnu Nair47074b82020-08-14 11:54:47 -07006866 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006867 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006868 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006869
6870 // Once a focused event arrives, we get an ANR for this application
6871 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6872 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07006873 const std::chrono::duration eventInjectionTimeout = 100ms;
6874 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006875 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006876 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07006877 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
6878 /*allowKeyRepeat=*/false);
6879 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
6880 << "result=" << ftl::enum_string(result);
6881 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
6882 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
6883 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
6884 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006885
Vishnu Naire4df8752022-09-08 09:17:55 -07006886 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006887 // ANR should not be raised again. It is up to policy to do that if it desires.
6888 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006889
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006890 // If we now get a focused window, the ANR should stop, but the policy handles that via
6891 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006892 ASSERT_TRUE(mDispatcher->waitForIdle());
6893}
6894
6895// We have a focused application, but no focused window
6896TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006897 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006898 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006899 mWindow->consumeFocusEvent(false);
6900
6901 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006902 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006903
Vishnu Naire4df8752022-09-08 09:17:55 -07006904 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6905 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006906
6907 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006908 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006909 ASSERT_TRUE(mDispatcher->waitForIdle());
6910 mWindow->assertNoEvents();
6911}
6912
6913/**
6914 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6915 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6916 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6917 * the ANR mechanism should still work.
6918 *
6919 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6920 * DOWN event, while not responding on the second one.
6921 */
6922TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6923 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006924 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6926 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6927 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006928 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006929
6930 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006931 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006932 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6933 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6934 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006935 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006936
6937 // We have now sent down and up. Let's consume first event and then ANR on the second.
6938 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6939 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006940 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006941}
6942
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006943// A spy window can receive an ANR
6944TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6945 sp<FakeWindowHandle> spy = addSpyWindow();
6946
6947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006948 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006949 WINDOW_LOCATION));
6950 mWindow->consumeMotionDown();
6951
6952 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6953 ASSERT_TRUE(sequenceNum);
6954 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006955 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006956
6957 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006958 spy->consumeMotionEvent(
6959 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006960 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006961 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006962}
6963
6964// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006965// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006966TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6967 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006968
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006970 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006971 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006973
6974 // Stuck on the ACTION_UP
6975 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006976 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006977
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006978 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006979 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006980 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6981 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006982
6983 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6984 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006985 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006986 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006987 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006988}
6989
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006990// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006991// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006992TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6993 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006994
6995 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006996 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6997 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006998
6999 mWindow->consumeMotionDown();
7000 // Stuck on the ACTION_UP
7001 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007002 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007003
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007004 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007005 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007006 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7007 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007008
7009 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7010 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007011 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007012 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007013 spy->assertNoEvents();
7014}
7015
7016TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007017 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007018
7019 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7020
7021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007022 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007023 WINDOW_LOCATION));
7024
7025 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7026 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7027 ASSERT_TRUE(consumeSeq);
7028
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007029 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7030 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007031
7032 monitor.finishEvent(*consumeSeq);
7033 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7034
7035 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007036 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007037}
7038
7039// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7040// process events, you don't get an anr. When the window later becomes unresponsive again, you
7041// get an ANR again.
7042// 1. tap -> block on ACTION_UP -> receive ANR
7043// 2. consume all pending events (= queue becomes healthy again)
7044// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7045TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7046 tapOnWindow();
7047
7048 mWindow->consumeMotionDown();
7049 // Block on ACTION_UP
7050 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007051 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007052 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7053 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007054 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007055 mWindow->assertNoEvents();
7056
7057 tapOnWindow();
7058 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007059 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007060 mWindow->consumeMotionUp();
7061
7062 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007063 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007064 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007065 mWindow->assertNoEvents();
7066}
7067
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007068// If a connection remains unresponsive for a while, make sure policy is only notified once about
7069// it.
7070TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007072 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007073 WINDOW_LOCATION));
7074
7075 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007076 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007077 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007078 // 'notifyConnectionUnresponsive' should only be called once per connection
7079 mFakePolicy->assertNotifyAnrWasNotCalled();
7080 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007081 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007082 mWindow->consumeMotionEvent(
7083 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007084 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007085 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007086 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007087 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007088}
7089
7090/**
7091 * 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 -07007092 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007093 *
7094 * Warning!!!
7095 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7096 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007097 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007098 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7099 *
7100 * If that value changes, this test should also change.
7101 */
7102TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7103 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007104 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007105
7106 tapOnWindow();
7107 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7108 ASSERT_TRUE(downSequenceNum);
7109 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7110 ASSERT_TRUE(upSequenceNum);
7111 // Don't finish the events yet, and send a key
7112 // Injection will "succeed" because we will eventually give up and send the key to the focused
7113 // window even if motions are still being processed. But because the injection timeout is short,
7114 // we will receive INJECTION_TIMED_OUT as the result.
7115
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007116 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007117 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7118 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007119 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007120 // Key will not be sent to the window, yet, because the window is still processing events
7121 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007122 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7123 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7124 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7125 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007126
7127 std::this_thread::sleep_for(500ms);
7128 // if we wait long enough though, dispatcher will give up, and still send the key
7129 // to the focused window, even though we have not yet finished the motion event
7130 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7131 mWindow->finishEvent(*downSequenceNum);
7132 mWindow->finishEvent(*upSequenceNum);
7133}
7134
7135/**
7136 * If a window is processing a motion event, and then a key event comes in, the key event should
7137 * not go to the focused window until the motion is processed.
7138 * If then a new motion comes in, then the pending key event should be going to the currently
7139 * focused window right away.
7140 */
7141TEST_F(InputDispatcherSingleWindowAnr,
7142 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7143 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007144 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145
7146 tapOnWindow();
7147 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7148 ASSERT_TRUE(downSequenceNum);
7149 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7150 ASSERT_TRUE(upSequenceNum);
7151 // Don't finish the events yet, and send a key
7152 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007154 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7155 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007156 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007157 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7158 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7159 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7160 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007161
7162 // Now tap down again. It should cause the pending key to go to the focused window right away.
7163 tapOnWindow();
7164 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7165 // the other events yet. We can finish events in any order.
7166 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7167 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7168 mWindow->consumeMotionDown();
7169 mWindow->consumeMotionUp();
7170 mWindow->assertNoEvents();
7171}
7172
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007173/**
7174 * Send an event to the app and have the app not respond right away.
7175 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7176 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7177 * At some point, the window becomes responsive again.
7178 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7179 */
7180TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7181 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7182 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7183 .build());
7184
7185 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7186 ASSERT_TRUE(sequenceNum);
7187 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7188 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7189
7190 mWindow->finishEvent(*sequenceNum);
7191 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7192 ASSERT_TRUE(mDispatcher->waitForIdle());
7193 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7194
7195 // Now that the window is responsive, let's continue the gesture.
7196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7197 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7198 .build());
7199
7200 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7201 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7202 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7203 .build());
7204
7205 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7206 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7207 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7208 .build());
7209 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7210 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7211 .build());
7212 // We already canceled this pointer, so the window shouldn't get any new events.
7213 mWindow->assertNoEvents();
7214
7215 // Start another one.
7216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7217 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7218 .build());
7219 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7220}
7221
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007222class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7223 virtual void SetUp() override {
7224 InputDispatcherTest::SetUp();
7225
Chris Yea209fde2020-07-22 13:54:51 -07007226 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007227 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007228 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7229 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007230 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007231 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007232 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007233
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007234 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7235 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007236 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007237 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007238
7239 // Set focused application.
7240 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007241 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007242
7243 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007244 mDispatcher->onWindowInfosChanged(
7245 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007246 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007247 mFocusedWindow->consumeFocusEvent(true);
7248 }
7249
7250 virtual void TearDown() override {
7251 InputDispatcherTest::TearDown();
7252
7253 mUnfocusedWindow.clear();
7254 mFocusedWindow.clear();
7255 }
7256
7257protected:
Chris Yea209fde2020-07-22 13:54:51 -07007258 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007259 sp<FakeWindowHandle> mUnfocusedWindow;
7260 sp<FakeWindowHandle> mFocusedWindow;
7261 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7262 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7263 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7264
7265 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7266
7267 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7268
7269private:
7270 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007272 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007273 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007275 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007276 location));
7277 }
7278};
7279
7280// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7281// should be ANR'd first.
7282TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007284 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007285 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007286 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007287 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007288 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007289 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007290 // We consumed all events, so no ANR
7291 ASSERT_TRUE(mDispatcher->waitForIdle());
7292 mFakePolicy->assertNotifyAnrWasNotCalled();
7293
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007295 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007296 FOCUSED_WINDOW_LOCATION));
7297 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7298 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007299
7300 const std::chrono::duration timeout =
7301 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007302 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007303 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7304 // sequence to make it consistent
7305 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007306 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007307 mFocusedWindow->consumeMotionDown();
7308 // This cancel is generated because the connection was unresponsive
7309 mFocusedWindow->consumeMotionCancel();
7310 mFocusedWindow->assertNoEvents();
7311 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007312 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007313 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7314 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007315 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007316}
7317
7318// If we have 2 windows with identical timeouts that are both unresponsive,
7319// it doesn't matter which order they should have ANR.
7320// But we should receive ANR for both.
7321TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7322 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007323 mUnfocusedWindow->setDispatchingTimeout(
7324 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007325 mDispatcher->onWindowInfosChanged(
7326 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007327
7328 tapOnFocusedWindow();
7329 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007330 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007331 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7332 mFocusedWindow->getDispatchingTimeout(
7333 DISPATCHING_TIMEOUT)),
7334 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7335
7336 ASSERT_THAT(anrConnectionTokens,
7337 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7338 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007339
7340 ASSERT_TRUE(mDispatcher->waitForIdle());
7341 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007342
7343 mFocusedWindow->consumeMotionDown();
7344 mFocusedWindow->consumeMotionUp();
7345 mUnfocusedWindow->consumeMotionOutside();
7346
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007347 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7348 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007349
7350 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007351 ASSERT_THAT(responsiveTokens,
7352 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7353 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007354 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007355}
7356
7357// If a window is already not responding, the second tap on the same window should be ignored.
7358// We should also log an error to account for the dropped event (not tested here).
7359// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7360TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7361 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007362 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007363 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007364 // Receive the events, but don't respond
7365 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7366 ASSERT_TRUE(downEventSequenceNum);
7367 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7368 ASSERT_TRUE(upEventSequenceNum);
7369 const std::chrono::duration timeout =
7370 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007371 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007372
7373 // Tap once again
7374 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007375 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007376 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007377 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007378 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007379 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007380 FOCUSED_WINDOW_LOCATION));
7381 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7382 // valid touch target
7383 mUnfocusedWindow->assertNoEvents();
7384
7385 // Consume the first tap
7386 mFocusedWindow->finishEvent(*downEventSequenceNum);
7387 mFocusedWindow->finishEvent(*upEventSequenceNum);
7388 ASSERT_TRUE(mDispatcher->waitForIdle());
7389 // The second tap did not go to the focused window
7390 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007391 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007392 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7393 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007394 mFakePolicy->assertNotifyAnrWasNotCalled();
7395}
7396
7397// If you tap outside of all windows, there will not be ANR
7398TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007399 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007400 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007401 LOCATION_OUTSIDE_ALL_WINDOWS));
7402 ASSERT_TRUE(mDispatcher->waitForIdle());
7403 mFakePolicy->assertNotifyAnrWasNotCalled();
7404}
7405
7406// Since the focused window is paused, tapping on it should not produce any events
7407TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7408 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007409 mDispatcher->onWindowInfosChanged(
7410 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007411
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007412 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007413 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007414 FOCUSED_WINDOW_LOCATION));
7415
7416 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7417 ASSERT_TRUE(mDispatcher->waitForIdle());
7418 // Should not ANR because the window is paused, and touches shouldn't go to it
7419 mFakePolicy->assertNotifyAnrWasNotCalled();
7420
7421 mFocusedWindow->assertNoEvents();
7422 mUnfocusedWindow->assertNoEvents();
7423}
7424
7425/**
7426 * 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 -07007427 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007428 * If a different window becomes focused at this time, the key should go to that window instead.
7429 *
7430 * Warning!!!
7431 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7432 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007433 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007434 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7435 *
7436 * If that value changes, this test should also change.
7437 */
7438TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7439 // Set a long ANR timeout to prevent it from triggering
7440 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007441 mDispatcher->onWindowInfosChanged(
7442 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007443
7444 tapOnUnfocusedWindow();
7445 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7446 ASSERT_TRUE(downSequenceNum);
7447 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7448 ASSERT_TRUE(upSequenceNum);
7449 // Don't finish the events yet, and send a key
7450 // Injection will succeed because we will eventually give up and send the key to the focused
7451 // window even if motions are still being processed.
7452
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007453 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007454 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7455 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007457 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007458 // and the key remains pending, waiting for the touch events to be processed.
7459 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7460 // under the hood.
7461 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7462 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007463
7464 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007465 mFocusedWindow->setFocusable(false);
7466 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007467 mDispatcher->onWindowInfosChanged(
7468 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007469 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007470
7471 // Focus events should precede the key events
7472 mUnfocusedWindow->consumeFocusEvent(true);
7473 mFocusedWindow->consumeFocusEvent(false);
7474
7475 // Finish the tap events, which should unblock dispatcher
7476 mUnfocusedWindow->finishEvent(*downSequenceNum);
7477 mUnfocusedWindow->finishEvent(*upSequenceNum);
7478
7479 // Now that all queues are cleared and no backlog in the connections, the key event
7480 // can finally go to the newly focused "mUnfocusedWindow".
7481 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7482 mFocusedWindow->assertNoEvents();
7483 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007484 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007485}
7486
7487// When the touch stream is split across 2 windows, and one of them does not respond,
7488// then ANR should be raised and the touch should be canceled for the unresponsive window.
7489// The other window should not be affected by that.
7490TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7491 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007492 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7493 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7494 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007495 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007496 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007497
7498 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007499 mDispatcher->notifyMotion(
7500 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7501 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007502
7503 const std::chrono::duration timeout =
7504 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007505 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007506
7507 mUnfocusedWindow->consumeMotionDown();
7508 mFocusedWindow->consumeMotionDown();
7509 // Focused window may or may not receive ACTION_MOVE
7510 // But it should definitely receive ACTION_CANCEL due to the ANR
7511 InputEvent* event;
7512 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7513 ASSERT_TRUE(moveOrCancelSequenceNum);
7514 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7515 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007516 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007517 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7518 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7519 mFocusedWindow->consumeMotionCancel();
7520 } else {
7521 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7522 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007523 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007524 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7525 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007526
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007527 mUnfocusedWindow->assertNoEvents();
7528 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007529 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007530}
7531
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007532/**
7533 * If we have no focused window, and a key comes in, we start the ANR timer.
7534 * The focused application should add a focused window before the timer runs out to prevent ANR.
7535 *
7536 * If the user touches another application during this time, the key should be dropped.
7537 * Next, if a new focused window comes in, without toggling the focused application,
7538 * then no ANR should occur.
7539 *
7540 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7541 * but in some cases the policy may not update the focused application.
7542 */
7543TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7544 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7545 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007546 focusedApplication->setDispatchingTimeout(200ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007547 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7548 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7549 mFocusedWindow->setFocusable(false);
7550
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007551 mDispatcher->onWindowInfosChanged(
7552 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007553 mFocusedWindow->consumeFocusEvent(false);
7554
7555 // Send a key. The ANR timer should start because there is no focused window.
7556 // 'focusedApplication' will get blamed if this timer completes.
7557 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007558 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007559 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7560 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00007561 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007563
7564 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7565 // then the injected touches won't cause the focused event to get dropped.
7566 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7567 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7568 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7569 // For this test, it means that the key would get delivered to the window once it becomes
7570 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007571 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007572
7573 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007574 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7575 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7576 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007577
7578 // We do not consume the motion right away, because that would require dispatcher to first
7579 // process (== drop) the key event, and by that time, ANR will be raised.
7580 // Set the focused window first.
7581 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007582 mDispatcher->onWindowInfosChanged(
7583 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007584 setFocusedWindow(mFocusedWindow);
7585 mFocusedWindow->consumeFocusEvent(true);
7586 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7587 // to another application. This could be a bug / behaviour in the policy.
7588
7589 mUnfocusedWindow->consumeMotionDown();
7590
7591 ASSERT_TRUE(mDispatcher->waitForIdle());
7592 // Should not ANR because we actually have a focused window. It was just added too slowly.
7593 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7594}
7595
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007596// These tests ensure we cannot send touch events to a window that's positioned behind a window
7597// that has feature NO_INPUT_CHANNEL.
7598// Layout:
7599// Top (closest to user)
7600// mNoInputWindow (above all windows)
7601// mBottomWindow
7602// Bottom (furthest from user)
7603class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7604 virtual void SetUp() override {
7605 InputDispatcherTest::SetUp();
7606
7607 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007608 mNoInputWindow =
7609 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7610 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007611 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007612 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007613 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7614 // It's perfectly valid for this window to not have an associated input channel
7615
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007616 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7617 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007618 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7619
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007620 mDispatcher->onWindowInfosChanged(
7621 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007622 }
7623
7624protected:
7625 std::shared_ptr<FakeApplicationHandle> mApplication;
7626 sp<FakeWindowHandle> mNoInputWindow;
7627 sp<FakeWindowHandle> mBottomWindow;
7628};
7629
7630TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7631 PointF touchedPoint = {10, 10};
7632
Prabir Pradhan678438e2023-04-13 19:32:51 +00007633 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7634 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7635 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007636
7637 mNoInputWindow->assertNoEvents();
7638 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7639 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7640 // and therefore should prevent mBottomWindow from receiving touches
7641 mBottomWindow->assertNoEvents();
7642}
7643
7644/**
7645 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7646 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7647 */
7648TEST_F(InputDispatcherMultiWindowOcclusionTests,
7649 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007650 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7651 "Window with input channel and NO_INPUT_CHANNEL",
7652 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007653
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007654 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007655 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007656 mDispatcher->onWindowInfosChanged(
7657 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007658
7659 PointF touchedPoint = {10, 10};
7660
Prabir Pradhan678438e2023-04-13 19:32:51 +00007661 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7662 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7663 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007664
7665 mNoInputWindow->assertNoEvents();
7666 mBottomWindow->assertNoEvents();
7667}
7668
Vishnu Nair958da932020-08-21 17:12:37 -07007669class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7670protected:
7671 std::shared_ptr<FakeApplicationHandle> mApp;
7672 sp<FakeWindowHandle> mWindow;
7673 sp<FakeWindowHandle> mMirror;
7674
7675 virtual void SetUp() override {
7676 InputDispatcherTest::SetUp();
7677 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007678 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7679 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7680 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007681 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7682 mWindow->setFocusable(true);
7683 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007684 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007685 }
7686};
7687
7688TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7689 // Request focus on a mirrored window
7690 setFocusedWindow(mMirror);
7691
7692 // window gets focused
7693 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007695 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007696 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7697}
7698
7699// A focused & mirrored window remains focused only if the window and its mirror are both
7700// focusable.
7701TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7702 setFocusedWindow(mMirror);
7703
7704 // window gets focused
7705 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007707 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007708 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007710 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007711 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7712
7713 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007714 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007715
7716 // window loses focus since one of the windows associated with the token in not focusable
7717 mWindow->consumeFocusEvent(false);
7718
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007719 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007720 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007721 mWindow->assertNoEvents();
7722}
7723
7724// A focused & mirrored window remains focused until the window and its mirror both become
7725// invisible.
7726TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7727 setFocusedWindow(mMirror);
7728
7729 // window gets focused
7730 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007732 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007733 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007735 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007736 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7737
7738 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007739 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007740
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007742 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007743 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007745 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007746 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7747
7748 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007749 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007750
7751 // window loses focus only after all windows associated with the token become invisible.
7752 mWindow->consumeFocusEvent(false);
7753
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007754 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007755 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007756 mWindow->assertNoEvents();
7757}
7758
7759// A focused & mirrored window remains focused until both windows are removed.
7760TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7761 setFocusedWindow(mMirror);
7762
7763 // window gets focused
7764 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007766 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007767 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007769 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007770 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7771
7772 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007773 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007774
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007776 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007777 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007779 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007780 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7781
7782 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007783 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007784 mWindow->consumeFocusEvent(false);
7785
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007786 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007787 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007788 mWindow->assertNoEvents();
7789}
7790
7791// Focus request can be pending until one window becomes visible.
7792TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7793 // Request focus on an invisible mirror.
7794 mWindow->setVisible(false);
7795 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007796 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007797 setFocusedWindow(mMirror);
7798
7799 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007801 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7802 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007803
7804 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007805 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007806
7807 // window gets focused
7808 mWindow->consumeFocusEvent(true);
7809 // window gets the pending key event
7810 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7811}
Prabir Pradhan99987712020-11-10 18:43:05 -08007812
7813class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7814protected:
7815 std::shared_ptr<FakeApplicationHandle> mApp;
7816 sp<FakeWindowHandle> mWindow;
7817 sp<FakeWindowHandle> mSecondWindow;
7818
7819 void SetUp() override {
7820 InputDispatcherTest::SetUp();
7821 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007822 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007823 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007824 mSecondWindow =
7825 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007826 mSecondWindow->setFocusable(true);
7827
7828 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007829 mDispatcher->onWindowInfosChanged(
7830 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08007831
7832 setFocusedWindow(mWindow);
7833 mWindow->consumeFocusEvent(true);
7834 }
7835
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007836 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007837 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007838 }
7839
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007840 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7841 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007842 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007843 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7844 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007845 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007846 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007847 }
7848};
7849
7850TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7851 // Ensure that capture cannot be obtained for unfocused windows.
7852 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7853 mFakePolicy->assertSetPointerCaptureNotCalled();
7854 mSecondWindow->assertNoEvents();
7855
7856 // Ensure that capture can be enabled from the focus window.
7857 requestAndVerifyPointerCapture(mWindow, true);
7858
7859 // Ensure that capture cannot be disabled from a window that does not have capture.
7860 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7861 mFakePolicy->assertSetPointerCaptureNotCalled();
7862
7863 // Ensure that capture can be disabled from the window with capture.
7864 requestAndVerifyPointerCapture(mWindow, false);
7865}
7866
7867TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007868 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007869
7870 setFocusedWindow(mSecondWindow);
7871
7872 // Ensure that the capture disabled event was sent first.
7873 mWindow->consumeCaptureEvent(false);
7874 mWindow->consumeFocusEvent(false);
7875 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007876 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007877
7878 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007879 notifyPointerCaptureChanged({});
7880 notifyPointerCaptureChanged(request);
7881 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007882 mWindow->assertNoEvents();
7883 mSecondWindow->assertNoEvents();
7884 mFakePolicy->assertSetPointerCaptureNotCalled();
7885}
7886
7887TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007888 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007889
7890 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007891 notifyPointerCaptureChanged({});
7892 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007893
7894 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007895 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007896 mWindow->consumeCaptureEvent(false);
7897 mWindow->assertNoEvents();
7898}
7899
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007900TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7901 requestAndVerifyPointerCapture(mWindow, true);
7902
7903 // The first window loses focus.
7904 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007905 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007906 mWindow->consumeCaptureEvent(false);
7907
7908 // Request Pointer Capture from the second window before the notification from InputReader
7909 // arrives.
7910 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007911 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007912
7913 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007914 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007915
7916 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007917 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007918
7919 mSecondWindow->consumeFocusEvent(true);
7920 mSecondWindow->consumeCaptureEvent(true);
7921}
7922
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007923TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7924 // App repeatedly enables and disables capture.
7925 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7926 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7927 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7928 mFakePolicy->assertSetPointerCaptureCalled(false);
7929 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7930 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7931
7932 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7933 // first request is now stale, this should do nothing.
7934 notifyPointerCaptureChanged(firstRequest);
7935 mWindow->assertNoEvents();
7936
7937 // InputReader notifies that the second request was enabled.
7938 notifyPointerCaptureChanged(secondRequest);
7939 mWindow->consumeCaptureEvent(true);
7940}
7941
Prabir Pradhan7092e262022-05-03 16:51:09 +00007942TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7943 requestAndVerifyPointerCapture(mWindow, true);
7944
7945 // App toggles pointer capture off and on.
7946 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7947 mFakePolicy->assertSetPointerCaptureCalled(false);
7948
7949 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7950 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7951
7952 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7953 // preceding "disable" request.
7954 notifyPointerCaptureChanged(enableRequest);
7955
7956 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7957 // any notifications.
7958 mWindow->assertNoEvents();
7959}
7960
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007961class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7962protected:
7963 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007964
7965 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7966 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7967
7968 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7969 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7970
7971 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7972 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7973 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7974 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7975 MAXIMUM_OBSCURING_OPACITY);
7976
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007977 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7978 static constexpr gui::Uid APP_B_UID{10002};
7979 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007980
7981 sp<FakeWindowHandle> mTouchWindow;
7982
7983 virtual void SetUp() override {
7984 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007985 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007986 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7987 }
7988
7989 virtual void TearDown() override {
7990 InputDispatcherTest::TearDown();
7991 mTouchWindow.clear();
7992 }
7993
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007994 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007995 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007996 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007997 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007998 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007999 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008000 return window;
8001 }
8002
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008003 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008004 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8005 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008006 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008007 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008008 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008009 return window;
8010 }
8011
8012 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008013 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8015 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008016 }
8017};
8018
8019TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008020 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008021 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008022 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008023
8024 touch();
8025
8026 mTouchWindow->assertNoEvents();
8027}
8028
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008029TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008030 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8031 const sp<FakeWindowHandle>& w =
8032 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008033 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008034
8035 touch();
8036
8037 mTouchWindow->assertNoEvents();
8038}
8039
8040TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008041 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8042 const sp<FakeWindowHandle>& w =
8043 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008044 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008045
8046 touch();
8047
8048 w->assertNoEvents();
8049}
8050
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008051TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008052 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008053 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008054
8055 touch();
8056
8057 mTouchWindow->consumeAnyMotionDown();
8058}
8059
8060TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008061 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008062 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008063 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008064 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008065
8066 touch({PointF{100, 100}});
8067
8068 mTouchWindow->consumeAnyMotionDown();
8069}
8070
8071TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008072 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008073 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008074 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008075
8076 touch();
8077
8078 mTouchWindow->consumeAnyMotionDown();
8079}
8080
8081TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8082 const sp<FakeWindowHandle>& w =
8083 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008084 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008085
8086 touch();
8087
8088 mTouchWindow->consumeAnyMotionDown();
8089}
8090
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008091TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8092 const sp<FakeWindowHandle>& w =
8093 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008094 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008095
8096 touch();
8097
8098 w->assertNoEvents();
8099}
8100
8101/**
8102 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8103 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8104 * window, the occluding window will still receive ACTION_OUTSIDE event.
8105 */
8106TEST_F(InputDispatcherUntrustedTouchesTest,
8107 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8108 const sp<FakeWindowHandle>& w =
8109 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008110 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008111 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008112
8113 touch();
8114
8115 w->consumeMotionOutside();
8116}
8117
8118TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8119 const sp<FakeWindowHandle>& w =
8120 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008121 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008122 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008123
8124 touch();
8125
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008126 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008127}
8128
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008129TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008130 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008131 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8132 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008133 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008134
8135 touch();
8136
8137 mTouchWindow->consumeAnyMotionDown();
8138}
8139
8140TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8141 const sp<FakeWindowHandle>& w =
8142 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8143 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008144 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008145
8146 touch();
8147
8148 mTouchWindow->consumeAnyMotionDown();
8149}
8150
8151TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008152 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008153 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8154 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008155 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008156
8157 touch();
8158
8159 mTouchWindow->assertNoEvents();
8160}
8161
8162TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8163 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8164 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008165 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8166 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008167 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008168 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8169 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008170 mDispatcher->onWindowInfosChanged(
8171 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008172
8173 touch();
8174
8175 mTouchWindow->assertNoEvents();
8176}
8177
8178TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8179 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8180 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008181 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8182 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008183 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008184 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8185 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008186 mDispatcher->onWindowInfosChanged(
8187 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008188
8189 touch();
8190
8191 mTouchWindow->consumeAnyMotionDown();
8192}
8193
8194TEST_F(InputDispatcherUntrustedTouchesTest,
8195 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8196 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008197 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8198 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008199 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008200 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8201 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008202 mDispatcher->onWindowInfosChanged(
8203 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008204
8205 touch();
8206
8207 mTouchWindow->consumeAnyMotionDown();
8208}
8209
8210TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8211 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008212 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8213 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008214 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008215 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8216 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008217 mDispatcher->onWindowInfosChanged(
8218 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008219
8220 touch();
8221
8222 mTouchWindow->assertNoEvents();
8223}
8224
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008225TEST_F(InputDispatcherUntrustedTouchesTest,
8226 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8227 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008228 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8229 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008230 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008231 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8232 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008233 mDispatcher->onWindowInfosChanged(
8234 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008235
8236 touch();
8237
8238 mTouchWindow->assertNoEvents();
8239}
8240
8241TEST_F(InputDispatcherUntrustedTouchesTest,
8242 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8243 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008244 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8245 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008246 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008247 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8248 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008249 mDispatcher->onWindowInfosChanged(
8250 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008251
8252 touch();
8253
8254 mTouchWindow->consumeAnyMotionDown();
8255}
8256
8257TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8258 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008259 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8260 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008261 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008262
8263 touch();
8264
8265 mTouchWindow->consumeAnyMotionDown();
8266}
8267
8268TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8269 const sp<FakeWindowHandle>& w =
8270 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008271 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008272
8273 touch();
8274
8275 mTouchWindow->consumeAnyMotionDown();
8276}
8277
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008278TEST_F(InputDispatcherUntrustedTouchesTest,
8279 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8280 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8281 const sp<FakeWindowHandle>& w =
8282 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008283 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008284
8285 touch();
8286
8287 mTouchWindow->assertNoEvents();
8288}
8289
8290TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8291 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8292 const sp<FakeWindowHandle>& w =
8293 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008294 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008295
8296 touch();
8297
8298 mTouchWindow->consumeAnyMotionDown();
8299}
8300
8301TEST_F(InputDispatcherUntrustedTouchesTest,
8302 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8303 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8304 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008305 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8306 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008307 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008308
8309 touch();
8310
8311 mTouchWindow->consumeAnyMotionDown();
8312}
8313
8314TEST_F(InputDispatcherUntrustedTouchesTest,
8315 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8316 const sp<FakeWindowHandle>& w1 =
8317 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8318 OPACITY_BELOW_THRESHOLD);
8319 const sp<FakeWindowHandle>& w2 =
8320 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8321 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008322 mDispatcher->onWindowInfosChanged(
8323 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008324
8325 touch();
8326
8327 mTouchWindow->assertNoEvents();
8328}
8329
8330/**
8331 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8332 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8333 * (which alone would result in allowing touches) does not affect the blocking behavior.
8334 */
8335TEST_F(InputDispatcherUntrustedTouchesTest,
8336 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8337 const sp<FakeWindowHandle>& wB =
8338 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8339 OPACITY_BELOW_THRESHOLD);
8340 const sp<FakeWindowHandle>& wC =
8341 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8342 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008343 mDispatcher->onWindowInfosChanged(
8344 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008345
8346 touch();
8347
8348 mTouchWindow->assertNoEvents();
8349}
8350
8351/**
8352 * This test is testing that a window from a different UID but with same application token doesn't
8353 * block the touch. Apps can share the application token for close UI collaboration for example.
8354 */
8355TEST_F(InputDispatcherUntrustedTouchesTest,
8356 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8357 const sp<FakeWindowHandle>& w =
8358 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8359 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008360 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008361
8362 touch();
8363
8364 mTouchWindow->consumeAnyMotionDown();
8365}
8366
arthurhungb89ccb02020-12-30 16:19:01 +08008367class InputDispatcherDragTests : public InputDispatcherTest {
8368protected:
8369 std::shared_ptr<FakeApplicationHandle> mApp;
8370 sp<FakeWindowHandle> mWindow;
8371 sp<FakeWindowHandle> mSecondWindow;
8372 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008373 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008374 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8375 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008376
8377 void SetUp() override {
8378 InputDispatcherTest::SetUp();
8379 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008380 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008381 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008382
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008383 mSecondWindow =
8384 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008385 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008386
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008387 mSpyWindow =
8388 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008389 mSpyWindow->setSpy(true);
8390 mSpyWindow->setTrustedOverlay(true);
8391 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8392
arthurhungb89ccb02020-12-30 16:19:01 +08008393 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008394 mDispatcher->onWindowInfosChanged(
8395 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8396 {},
8397 0,
8398 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008399 }
8400
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008401 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8402 switch (fromSource) {
8403 case AINPUT_SOURCE_TOUCHSCREEN:
8404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008405 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008406 ADISPLAY_ID_DEFAULT, {50, 50}))
8407 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8408 break;
8409 case AINPUT_SOURCE_STYLUS:
8410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008411 injectMotionEvent(*mDispatcher,
8412 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8413 AINPUT_SOURCE_STYLUS)
8414 .buttonState(
8415 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8416 .pointer(PointerBuilder(0, ToolType::STYLUS)
8417 .x(50)
8418 .y(50))
8419 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008420 break;
8421 case AINPUT_SOURCE_MOUSE:
8422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008423 injectMotionEvent(*mDispatcher,
8424 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8425 AINPUT_SOURCE_MOUSE)
8426 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8427 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8428 ToolType::MOUSE)
8429 .x(50)
8430 .y(50))
8431 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008432 break;
8433 default:
8434 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8435 }
arthurhungb89ccb02020-12-30 16:19:01 +08008436
8437 // Window should receive motion event.
8438 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008439 // Spy window should also receive motion event
8440 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008441 }
8442
8443 // Start performing drag, we will create a drag window and transfer touch to it.
8444 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8445 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008446 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008447 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008448 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008449 }
arthurhungb89ccb02020-12-30 16:19:01 +08008450
8451 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008452 mDragWindow =
8453 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008454 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008455 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8456 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8457 {},
8458 0,
8459 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008460
8461 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008462 bool transferred =
8463 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008464 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008465 if (transferred) {
8466 mWindow->consumeMotionCancel();
8467 mDragWindow->consumeMotionDown();
8468 }
8469 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008470 }
8471};
8472
8473TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008474 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008475
8476 // Move on window.
8477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008478 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008479 ADISPLAY_ID_DEFAULT, {50, 50}))
8480 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8481 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8482 mWindow->consumeDragEvent(false, 50, 50);
8483 mSecondWindow->assertNoEvents();
8484
8485 // Move to another window.
8486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008487 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008488 ADISPLAY_ID_DEFAULT, {150, 50}))
8489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8490 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8491 mWindow->consumeDragEvent(true, 150, 50);
8492 mSecondWindow->consumeDragEvent(false, 50, 50);
8493
8494 // Move back to original window.
8495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008496 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008497 ADISPLAY_ID_DEFAULT, {50, 50}))
8498 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8499 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8500 mWindow->consumeDragEvent(false, 50, 50);
8501 mSecondWindow->consumeDragEvent(true, -50, 50);
8502
8503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008504 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8505 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08008506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8507 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8508 mWindow->assertNoEvents();
8509 mSecondWindow->assertNoEvents();
8510}
8511
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008512TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008513 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008514
8515 // No cancel event after drag start
8516 mSpyWindow->assertNoEvents();
8517
8518 const MotionEvent secondFingerDownEvent =
8519 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8520 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008521 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8522 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008523 .build();
8524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008525 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008526 InputEventInjectionSync::WAIT_FOR_RESULT))
8527 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8528
8529 // Receives cancel for first pointer after next pointer down
8530 mSpyWindow->consumeMotionCancel();
8531 mSpyWindow->consumeMotionDown();
8532
8533 mSpyWindow->assertNoEvents();
8534}
8535
arthurhungf452d0b2021-01-06 00:19:52 +08008536TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008537 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008538
8539 // Move on window.
8540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008541 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08008542 ADISPLAY_ID_DEFAULT, {50, 50}))
8543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8544 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8545 mWindow->consumeDragEvent(false, 50, 50);
8546 mSecondWindow->assertNoEvents();
8547
8548 // Move to another window.
8549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008550 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08008551 ADISPLAY_ID_DEFAULT, {150, 50}))
8552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8553 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8554 mWindow->consumeDragEvent(true, 150, 50);
8555 mSecondWindow->consumeDragEvent(false, 50, 50);
8556
8557 // drop to another window.
8558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008559 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08008560 {150, 50}))
8561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8562 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008563 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008564 mWindow->assertNoEvents();
8565 mSecondWindow->assertNoEvents();
8566}
8567
arthurhung6d4bed92021-03-17 11:59:33 +08008568TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008569 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008570
8571 // Move on window and keep button pressed.
8572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008573 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008574 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8575 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008576 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008577 .build()))
8578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8579 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8580 mWindow->consumeDragEvent(false, 50, 50);
8581 mSecondWindow->assertNoEvents();
8582
8583 // Move to another window and release button, expect to drop item.
8584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008585 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008586 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8587 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008588 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008589 .build()))
8590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8591 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8592 mWindow->assertNoEvents();
8593 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008594 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008595
8596 // nothing to the window.
8597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008598 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08008599 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8600 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008601 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008602 .build()))
8603 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8604 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8605 mWindow->assertNoEvents();
8606 mSecondWindow->assertNoEvents();
8607}
8608
Arthur Hung54745652022-04-20 07:17:41 +00008609TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008610 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008611
8612 // Set second window invisible.
8613 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008614 mDispatcher->onWindowInfosChanged(
8615 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08008616
8617 // Move on window.
8618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008619 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008620 ADISPLAY_ID_DEFAULT, {50, 50}))
8621 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8622 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8623 mWindow->consumeDragEvent(false, 50, 50);
8624 mSecondWindow->assertNoEvents();
8625
8626 // Move to another window.
8627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008628 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008629 ADISPLAY_ID_DEFAULT, {150, 50}))
8630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8631 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8632 mWindow->consumeDragEvent(true, 150, 50);
8633 mSecondWindow->assertNoEvents();
8634
8635 // drop to another window.
8636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008637 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08008638 {150, 50}))
8639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8640 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008641 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008642 mWindow->assertNoEvents();
8643 mSecondWindow->assertNoEvents();
8644}
8645
Arthur Hung54745652022-04-20 07:17:41 +00008646TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008647 // Ensure window could track pointerIds if it didn't support split touch.
8648 mWindow->setPreventSplitting(true);
8649
Arthur Hung54745652022-04-20 07:17:41 +00008650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00008652 {50, 50}))
8653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8654 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8655
8656 const MotionEvent secondFingerDownEvent =
8657 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8658 .displayId(ADISPLAY_ID_DEFAULT)
8659 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008660 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8661 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008662 .build();
8663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008664 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008665 InputEventInjectionSync::WAIT_FOR_RESULT))
8666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008667 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008668
8669 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008670 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008671}
8672
8673TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8674 // First down on second window.
8675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008676 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00008677 {150, 50}))
8678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8679
8680 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8681
8682 // Second down on first window.
8683 const MotionEvent secondFingerDownEvent =
8684 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8685 .displayId(ADISPLAY_ID_DEFAULT)
8686 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008687 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8688 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008689 .build();
8690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008691 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008692 InputEventInjectionSync::WAIT_FOR_RESULT))
8693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8694 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8695
8696 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008697 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008698
8699 // Move on window.
8700 const MotionEvent secondFingerMoveEvent =
8701 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8702 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008703 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8704 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008705 .build();
8706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008707 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008708 InputEventInjectionSync::WAIT_FOR_RESULT));
8709 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8710 mWindow->consumeDragEvent(false, 50, 50);
8711 mSecondWindow->consumeMotionMove();
8712
8713 // Release the drag pointer should perform drop.
8714 const MotionEvent secondFingerUpEvent =
8715 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8716 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008717 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8718 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008719 .build();
8720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008721 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00008722 InputEventInjectionSync::WAIT_FOR_RESULT));
8723 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008724 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008725 mWindow->assertNoEvents();
8726 mSecondWindow->consumeMotionMove();
8727}
8728
Arthur Hung3915c1f2022-05-31 07:17:17 +00008729TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008730 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008731
8732 // Update window of second display.
8733 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008734 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008735 mDispatcher->onWindowInfosChanged(
8736 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8737 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8738 {},
8739 0,
8740 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008741
8742 // Let second display has a touch state.
8743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008744 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008745 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8746 AINPUT_SOURCE_TOUCHSCREEN)
8747 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008748 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008749 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008750 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008751 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008752 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008753 mDispatcher->onWindowInfosChanged(
8754 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
8755 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
8756 {},
8757 0,
8758 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00008759
8760 // Move on window.
8761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008762 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008763 ADISPLAY_ID_DEFAULT, {50, 50}))
8764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8765 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8766 mWindow->consumeDragEvent(false, 50, 50);
8767 mSecondWindow->assertNoEvents();
8768
8769 // Move to another window.
8770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008771 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008772 ADISPLAY_ID_DEFAULT, {150, 50}))
8773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8774 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8775 mWindow->consumeDragEvent(true, 150, 50);
8776 mSecondWindow->consumeDragEvent(false, 50, 50);
8777
8778 // drop to another window.
8779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008780 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00008781 {150, 50}))
8782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8783 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008784 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008785 mWindow->assertNoEvents();
8786 mSecondWindow->assertNoEvents();
8787}
8788
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008789TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8790 startDrag(true, AINPUT_SOURCE_MOUSE);
8791 // Move on window.
8792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008793 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008794 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8795 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008796 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008797 .x(50)
8798 .y(50))
8799 .build()))
8800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8801 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8802 mWindow->consumeDragEvent(false, 50, 50);
8803 mSecondWindow->assertNoEvents();
8804
8805 // Move to another window.
8806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008807 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008808 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8809 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008810 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008811 .x(150)
8812 .y(50))
8813 .build()))
8814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8815 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8816 mWindow->consumeDragEvent(true, 150, 50);
8817 mSecondWindow->consumeDragEvent(false, 50, 50);
8818
8819 // drop to another window.
8820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008821 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008822 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8823 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008824 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008825 .x(150)
8826 .y(50))
8827 .build()))
8828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8829 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008830 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008831 mWindow->assertNoEvents();
8832 mSecondWindow->assertNoEvents();
8833}
8834
Vishnu Nair062a8672021-09-03 16:07:44 -07008835class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8836
8837TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008839 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8840 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008841 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008842 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8843 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008844 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008845 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008846 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008847
8848 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008849 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008850 window->assertNoEvents();
8851
Prabir Pradhan678438e2023-04-13 19:32:51 +00008852 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8853 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008854 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8855 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008856 window->assertNoEvents();
8857
8858 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008859 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008860 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008861
Prabir Pradhan678438e2023-04-13 19:32:51 +00008862 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008863 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8864
Prabir Pradhan678438e2023-04-13 19:32:51 +00008865 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8866 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008867 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8868 window->assertNoEvents();
8869}
8870
8871TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8872 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8873 std::make_shared<FakeApplicationHandle>();
8874 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008875 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8876 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008877 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008878 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008879 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008881 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8882 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008883 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008884 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008885 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8886 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008887 mDispatcher->onWindowInfosChanged(
8888 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008889 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008890 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008891
8892 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008893 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008894 window->assertNoEvents();
8895
Prabir Pradhan678438e2023-04-13 19:32:51 +00008896 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8897 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008898 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8899 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008900 window->assertNoEvents();
8901
8902 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008903 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008904 mDispatcher->onWindowInfosChanged(
8905 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008906
Prabir Pradhan678438e2023-04-13 19:32:51 +00008907 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008908 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8909
Prabir Pradhan678438e2023-04-13 19:32:51 +00008910 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8911 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008912 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8913 window->assertNoEvents();
8914}
8915
8916TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8917 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8918 std::make_shared<FakeApplicationHandle>();
8919 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008920 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8921 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008922 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008923 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008924 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008926 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8927 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008928 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008929 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008930 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8931 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008932 mDispatcher->onWindowInfosChanged(
8933 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008934 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008935 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008936
8937 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008938 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008939 window->assertNoEvents();
8940
Prabir Pradhan678438e2023-04-13 19:32:51 +00008941 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8942 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008943 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8944 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008945 window->assertNoEvents();
8946
8947 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008948 mDispatcher->onWindowInfosChanged(
8949 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07008950
Prabir Pradhan678438e2023-04-13 19:32:51 +00008951 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008952 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8953
Prabir Pradhan678438e2023-04-13 19:32:51 +00008954 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8955 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008956 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8957 window->assertNoEvents();
8958}
8959
Antonio Kantekf16f2832021-09-28 04:39:20 +00008960class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8961protected:
8962 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008963 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008964 sp<FakeWindowHandle> mWindow;
8965 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008966 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008967
8968 void SetUp() override {
8969 InputDispatcherTest::SetUp();
8970
8971 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008972 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008973 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008974 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008975 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008976 mSecondWindow =
8977 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008978 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008979 mThirdWindow =
8980 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8981 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8982 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008983
8984 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008985 mDispatcher->onWindowInfosChanged(
8986 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
8987 {},
8988 0,
8989 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00008990 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008991 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008992
Antonio Kantek15beb512022-06-13 22:35:41 +00008993 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008994 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008995 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008996 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8997 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008998 mThirdWindow->assertNoEvents();
8999 }
9000
9001 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9002 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009003 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009004 SECOND_DISPLAY_ID)) {
9005 mWindow->assertNoEvents();
9006 mSecondWindow->assertNoEvents();
9007 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009008 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009009 }
9010
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009011 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009012 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009013 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9014 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009015 mWindow->consumeTouchModeEvent(inTouchMode);
9016 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009017 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009018 }
9019};
9020
Antonio Kantek26defcf2022-02-08 01:12:27 +00009021TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009022 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009023 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9024 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009025 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009026}
9027
Antonio Kantek26defcf2022-02-08 01:12:27 +00009028TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9029 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009030 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009031 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009032 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009033 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009034 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009035 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009036 mWindow->assertNoEvents();
9037 mSecondWindow->assertNoEvents();
9038}
9039
9040TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9041 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009042 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009043 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009044 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009045 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009046 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009047}
9048
Antonio Kantekf16f2832021-09-28 04:39:20 +00009049TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009050 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009051 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9052 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009053 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009054 mWindow->assertNoEvents();
9055 mSecondWindow->assertNoEvents();
9056}
9057
Antonio Kantek15beb512022-06-13 22:35:41 +00009058TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9059 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9060 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9061 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009062 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009063 mWindow->assertNoEvents();
9064 mSecondWindow->assertNoEvents();
9065 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9066}
9067
Antonio Kantek48710e42022-03-24 14:19:30 -07009068TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9069 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9071 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009072 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9073 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9074
9075 // Then remove focus.
9076 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009077 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009078
9079 // Assert that caller can switch touch mode by owning one of the last interacted window.
9080 const WindowInfo& windowInfo = *mWindow->getInfo();
9081 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9082 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009083 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009084}
9085
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009086class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9087public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009088 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009089 std::shared_ptr<FakeApplicationHandle> application =
9090 std::make_shared<FakeApplicationHandle>();
9091 std::string name = "Fake Spy ";
9092 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009093 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9094 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009095 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009096 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009097 return spy;
9098 }
9099
9100 sp<FakeWindowHandle> createForeground() {
9101 std::shared_ptr<FakeApplicationHandle> application =
9102 std::make_shared<FakeApplicationHandle>();
9103 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009104 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9105 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009106 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009107 return window;
9108 }
9109
9110private:
9111 int mSpyCount{0};
9112};
9113
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009114using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009115/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009116 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9117 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009118TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009119 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009120 ScopedSilentDeath _silentDeath;
9121
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009122 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009123 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009124 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009125 ".* not a trusted overlay");
9126}
9127
9128/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009129 * Input injection into a display with a spy window but no foreground windows should succeed.
9130 */
9131TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009132 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009133 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009134
9135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009136 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9138 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9139}
9140
9141/**
9142 * Verify the order in which different input windows receive events. The touched foreground window
9143 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9144 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9145 * receive events before ones belows it.
9146 *
9147 * Here, we set up a scenario with four windows in the following Z order from the top:
9148 * spy1, spy2, window, spy3.
9149 * We then inject an event and verify that the foreground "window" receives it first, followed by
9150 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9151 * window.
9152 */
9153TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9154 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009155 auto spy1 = createSpy();
9156 auto spy2 = createSpy();
9157 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009158 mDispatcher->onWindowInfosChanged(
9159 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009160 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9161 const size_t numChannels = channels.size();
9162
Michael Wright8e9a8562022-02-09 13:44:29 +00009163 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009164 if (!epollFd.ok()) {
9165 FAIL() << "Failed to create epoll fd";
9166 }
9167
9168 for (size_t i = 0; i < numChannels; i++) {
9169 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9170 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9171 FAIL() << "Failed to add fd to epoll";
9172 }
9173 }
9174
9175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009176 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9178
9179 std::vector<size_t> eventOrder;
9180 std::vector<struct epoll_event> events(numChannels);
9181 for (;;) {
9182 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9183 (100ms).count());
9184 if (nFds < 0) {
9185 FAIL() << "Failed to call epoll_wait";
9186 }
9187 if (nFds == 0) {
9188 break; // epoll_wait timed out
9189 }
9190 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009191 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009192 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009193 channels[i]->consumeMotionDown();
9194 }
9195 }
9196
9197 // Verify the order in which the events were received.
9198 EXPECT_EQ(3u, eventOrder.size());
9199 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9200 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9201 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9202}
9203
9204/**
9205 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9206 */
9207TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9208 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009209 auto spy = createSpy();
9210 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009211 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009212
9213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009214 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9216 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9217 spy->assertNoEvents();
9218}
9219
9220/**
9221 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9222 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9223 * to the window.
9224 */
9225TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9226 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009227 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009228 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009229 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009230
9231 // Inject an event outside the spy window's touchable region.
9232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009233 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9235 window->consumeMotionDown();
9236 spy->assertNoEvents();
9237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009238 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009239 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9240 window->consumeMotionUp();
9241 spy->assertNoEvents();
9242
9243 // Inject an event inside the spy window's touchable region.
9244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009245 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009246 {5, 10}))
9247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9248 window->consumeMotionDown();
9249 spy->consumeMotionDown();
9250}
9251
9252/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009253 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009254 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009255 */
9256TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9257 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009258 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009259 auto spy = createSpy();
9260 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009261 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009262 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009263 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009264
9265 // Inject an event outside the spy window's frame and touchable region.
9266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009267 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009268 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009269 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9270 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009271 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009272}
9273
9274/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009275 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9276 * pointers that are down within its bounds.
9277 */
9278TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9279 auto windowLeft = createForeground();
9280 windowLeft->setFrame({0, 0, 100, 200});
9281 auto windowRight = createForeground();
9282 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009283 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009284 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009285 mDispatcher->onWindowInfosChanged(
9286 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009287
9288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009289 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009290 {50, 50}))
9291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9292 windowLeft->consumeMotionDown();
9293 spy->consumeMotionDown();
9294
9295 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009296 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009297 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009298 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9299 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009300 .build();
9301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009302 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009303 InputEventInjectionSync::WAIT_FOR_RESULT))
9304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9305 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009306 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009307}
9308
9309/**
9310 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9311 * the spy should receive the second pointer with ACTION_DOWN.
9312 */
9313TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9314 auto window = createForeground();
9315 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009316 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009317 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009318 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009319
9320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009321 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009322 {50, 50}))
9323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9324 window->consumeMotionDown();
9325 spyRight->assertNoEvents();
9326
9327 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009328 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009329 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009330 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9331 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009332 .build();
9333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009334 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009335 InputEventInjectionSync::WAIT_FOR_RESULT))
9336 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009337 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009338 spyRight->consumeMotionDown();
9339}
9340
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009341/**
9342 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9343 * windows should be allowed to control split touch.
9344 */
9345TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009346 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009347 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009348 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009349 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009350
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009351 auto window = createForeground();
9352 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009353
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009354 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009355
9356 // First finger down, no window touched.
9357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009358 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009359 {100, 200}))
9360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9361 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9362 window->assertNoEvents();
9363
9364 // Second finger down on window, the window should receive touch down.
9365 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009366 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009367 .displayId(ADISPLAY_ID_DEFAULT)
9368 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009369 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9370 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009371 .build();
9372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009373 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009374 InputEventInjectionSync::WAIT_FOR_RESULT))
9375 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9376
9377 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009378 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009379}
9380
9381/**
9382 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9383 * do not receive key events.
9384 */
9385TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009386 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009387 spy->setFocusable(false);
9388
9389 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009390 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009391 setFocusedWindow(window);
9392 window->consumeFocusEvent(true);
9393
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009395 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9396 window->consumeKeyDown(ADISPLAY_ID_NONE);
9397
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009399 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9400 window->consumeKeyUp(ADISPLAY_ID_NONE);
9401
9402 spy->assertNoEvents();
9403}
9404
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009405using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9406
9407/**
9408 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9409 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9410 */
9411TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9412 auto window = createForeground();
9413 auto spy1 = createSpy();
9414 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009415 mDispatcher->onWindowInfosChanged(
9416 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009417
9418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009419 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009420 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9421 window->consumeMotionDown();
9422 spy1->consumeMotionDown();
9423 spy2->consumeMotionDown();
9424
9425 // Pilfer pointers from the second spy window.
9426 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9427 spy2->assertNoEvents();
9428 spy1->consumeMotionCancel();
9429 window->consumeMotionCancel();
9430
9431 // The rest of the gesture should only be sent to the second spy window.
9432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009433 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009434 ADISPLAY_ID_DEFAULT))
9435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9436 spy2->consumeMotionMove();
9437 spy1->assertNoEvents();
9438 window->assertNoEvents();
9439}
9440
9441/**
9442 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9443 * in the middle of the gesture.
9444 */
9445TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9446 auto window = createForeground();
9447 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009448 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009449
9450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009451 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9453 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9454 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9455
9456 window->releaseChannel();
9457
9458 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9459
9460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009461 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9463 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9464}
9465
9466/**
9467 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9468 * the spy, but not to any other windows.
9469 */
9470TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9471 auto spy = createSpy();
9472 auto window = createForeground();
9473
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009474 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009475
9476 // First finger down on the window and the spy.
9477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009478 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009479 {100, 200}))
9480 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9481 spy->consumeMotionDown();
9482 window->consumeMotionDown();
9483
9484 // Spy window pilfers the pointers.
9485 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9486 window->consumeMotionCancel();
9487
9488 // Second finger down on the window and spy, but the window should not receive the pointer down.
9489 const MotionEvent secondFingerDownEvent =
9490 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9491 .displayId(ADISPLAY_ID_DEFAULT)
9492 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009493 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9494 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009495 .build();
9496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009497 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009498 InputEventInjectionSync::WAIT_FOR_RESULT))
9499 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9500
Harry Cutts33476232023-01-30 19:57:29 +00009501 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009502
9503 // Third finger goes down outside all windows, so injection should fail.
9504 const MotionEvent thirdFingerDownEvent =
9505 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9506 .displayId(ADISPLAY_ID_DEFAULT)
9507 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009508 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9509 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9510 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009511 .build();
9512 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009513 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009514 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009515 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009516
9517 spy->assertNoEvents();
9518 window->assertNoEvents();
9519}
9520
9521/**
9522 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9523 */
9524TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9525 auto spy = createSpy();
9526 spy->setFrame(Rect(0, 0, 100, 100));
9527 auto window = createForeground();
9528 window->setFrame(Rect(0, 0, 200, 200));
9529
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009530 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009531
9532 // First finger down on the window only
9533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009534 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009535 {150, 150}))
9536 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9537 window->consumeMotionDown();
9538
9539 // Second finger down on the spy and window
9540 const MotionEvent secondFingerDownEvent =
9541 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9542 .displayId(ADISPLAY_ID_DEFAULT)
9543 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009544 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9545 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009546 .build();
9547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009548 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009549 InputEventInjectionSync::WAIT_FOR_RESULT))
9550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9551 spy->consumeMotionDown();
9552 window->consumeMotionPointerDown(1);
9553
9554 // Third finger down on the spy and window
9555 const MotionEvent thirdFingerDownEvent =
9556 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9557 .displayId(ADISPLAY_ID_DEFAULT)
9558 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009559 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9560 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9561 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009562 .build();
9563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009564 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009565 InputEventInjectionSync::WAIT_FOR_RESULT))
9566 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9567 spy->consumeMotionPointerDown(1);
9568 window->consumeMotionPointerDown(2);
9569
9570 // Spy window pilfers the pointers.
9571 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009572 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9573 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009574
9575 spy->assertNoEvents();
9576 window->assertNoEvents();
9577}
9578
9579/**
9580 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9581 * other windows should be canceled. If this results in the cancellation of all pointers for some
9582 * window, then that window should receive ACTION_CANCEL.
9583 */
9584TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9585 auto spy = createSpy();
9586 spy->setFrame(Rect(0, 0, 100, 100));
9587 auto window = createForeground();
9588 window->setFrame(Rect(0, 0, 200, 200));
9589
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009590 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009591
9592 // First finger down on both spy and window
9593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009594 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009595 {10, 10}))
9596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9597 window->consumeMotionDown();
9598 spy->consumeMotionDown();
9599
9600 // Second finger down on the spy and window
9601 const MotionEvent secondFingerDownEvent =
9602 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9603 .displayId(ADISPLAY_ID_DEFAULT)
9604 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009605 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9606 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009607 .build();
9608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009609 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009610 InputEventInjectionSync::WAIT_FOR_RESULT))
9611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9612 spy->consumeMotionPointerDown(1);
9613 window->consumeMotionPointerDown(1);
9614
9615 // Spy window pilfers the pointers.
9616 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9617 window->consumeMotionCancel();
9618
9619 spy->assertNoEvents();
9620 window->assertNoEvents();
9621}
9622
9623/**
9624 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9625 * be sent to other windows
9626 */
9627TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9628 auto spy = createSpy();
9629 spy->setFrame(Rect(0, 0, 100, 100));
9630 auto window = createForeground();
9631 window->setFrame(Rect(0, 0, 200, 200));
9632
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009633 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009634
9635 // First finger down on both window and spy
9636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009637 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009638 {10, 10}))
9639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9640 window->consumeMotionDown();
9641 spy->consumeMotionDown();
9642
9643 // Spy window pilfers the pointers.
9644 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9645 window->consumeMotionCancel();
9646
9647 // Second finger down on the window only
9648 const MotionEvent secondFingerDownEvent =
9649 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9650 .displayId(ADISPLAY_ID_DEFAULT)
9651 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009652 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9653 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009654 .build();
9655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009656 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009657 InputEventInjectionSync::WAIT_FOR_RESULT))
9658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9659 window->consumeMotionDown();
9660 window->assertNoEvents();
9661
9662 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9663 spy->consumeMotionMove();
9664 spy->assertNoEvents();
9665}
9666
Prabir Pradhand65552b2021-10-07 11:23:50 -07009667class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9668public:
9669 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9670 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9671 std::make_shared<FakeApplicationHandle>();
9672 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009673 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9674 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009675 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009676 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009677 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009678 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009679 overlay->setTrustedOverlay(true);
9680
9681 std::shared_ptr<FakeApplicationHandle> application =
9682 std::make_shared<FakeApplicationHandle>();
9683 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009684 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9685 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009686 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009687 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009688
9689 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009690 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009691 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009692 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009693 return {std::move(overlay), std::move(window)};
9694 }
9695
9696 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009697 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009698 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009699 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009700 }
9701
9702 void sendStylusEvent(int32_t action) {
9703 NotifyMotionArgs motionArgs =
9704 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9705 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009706 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009707 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009708 }
9709};
9710
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009711using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9712
9713TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009714 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009715 ScopedSilentDeath _silentDeath;
9716
Prabir Pradhand65552b2021-10-07 11:23:50 -07009717 auto [overlay, window] = setupStylusOverlayScenario();
9718 overlay->setTrustedOverlay(false);
9719 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009720 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
9721 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -07009722 ".* not a trusted overlay");
9723}
9724
9725TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9726 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009727 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009728
9729 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9730 overlay->consumeMotionDown();
9731 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9732 overlay->consumeMotionUp();
9733
9734 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9735 window->consumeMotionDown();
9736 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9737 window->consumeMotionUp();
9738
9739 overlay->assertNoEvents();
9740 window->assertNoEvents();
9741}
9742
9743TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9744 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009745 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009746 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009747
9748 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9749 overlay->consumeMotionDown();
9750 window->consumeMotionDown();
9751 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9752 overlay->consumeMotionUp();
9753 window->consumeMotionUp();
9754
9755 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9756 window->consumeMotionDown();
9757 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9758 window->consumeMotionUp();
9759
9760 overlay->assertNoEvents();
9761 window->assertNoEvents();
9762}
9763
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009764/**
9765 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9766 * The scenario is as follows:
9767 * - The stylus interceptor overlay is configured as a spy window.
9768 * - The stylus interceptor spy receives the start of a new stylus gesture.
9769 * - It pilfers pointers and then configures itself to no longer be a spy.
9770 * - The stylus interceptor continues to receive the rest of the gesture.
9771 */
9772TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9773 auto [overlay, window] = setupStylusOverlayScenario();
9774 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009775 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009776
9777 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9778 overlay->consumeMotionDown();
9779 window->consumeMotionDown();
9780
9781 // The interceptor pilfers the pointers.
9782 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9783 window->consumeMotionCancel();
9784
9785 // The interceptor configures itself so that it is no longer a spy.
9786 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009787 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009788
9789 // It continues to receive the rest of the stylus gesture.
9790 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9791 overlay->consumeMotionMove();
9792 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9793 overlay->consumeMotionUp();
9794
9795 window->assertNoEvents();
9796}
9797
Prabir Pradhan5735a322022-04-11 17:23:34 +00009798struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009799 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009800 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009801 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9802 std::unique_ptr<InputDispatcher>& mDispatcher;
9803
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009804 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009805 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9806
9807 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009808 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009809 ADISPLAY_ID_DEFAULT, {100, 200},
9810 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9811 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9812 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9813 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9814 }
9815
9816 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009817 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009818 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009819 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009820 mPolicyFlags);
9821 }
9822
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009823 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +00009824 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9825 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009826 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9827 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009828 window->setOwnerInfo(mPid, mUid);
9829 return window;
9830 }
9831};
9832
9833using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9834
9835TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009836 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009837 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009838 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009839
9840 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9841 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9842 window->consumeMotionDown();
9843
9844 setFocusedWindow(window);
9845 window->consumeFocusEvent(true);
9846
9847 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9848 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9849 window->consumeKeyDown(ADISPLAY_ID_NONE);
9850}
9851
9852TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009853 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009854 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009856
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009857 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009858 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9859 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9860
9861 setFocusedWindow(window);
9862 window->consumeFocusEvent(true);
9863
9864 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9865 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9866 window->assertNoEvents();
9867}
9868
9869TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009870 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009871 auto window = owner.createWindow("Owned window");
9872 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009873 spy->setSpy(true);
9874 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009875 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009876
9877 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9878 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9879 spy->consumeMotionDown();
9880 window->consumeMotionDown();
9881}
9882
9883TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009884 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009885 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009886
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009887 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009888 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009889 randosSpy->setSpy(true);
9890 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009891 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009892
9893 // The event is targeted at owner's window, so injection should succeed, but the spy should
9894 // not receive the event.
9895 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9896 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9897 randosSpy->assertNoEvents();
9898 window->consumeMotionDown();
9899}
9900
9901TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009902 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009903 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009904
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009905 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009906 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009907 randosSpy->setSpy(true);
9908 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009909 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009910
9911 // A user that has injection permission can inject into any window.
9912 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009913 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009914 ADISPLAY_ID_DEFAULT));
9915 randosSpy->consumeMotionDown();
9916 window->consumeMotionDown();
9917
9918 setFocusedWindow(randosSpy);
9919 randosSpy->consumeFocusEvent(true);
9920
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009921 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +00009922 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9923 window->assertNoEvents();
9924}
9925
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009926TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009927 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009928 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009929
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009930 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -07009931 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +00009932 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9933 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009934 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009935
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009936 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009937 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9938 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9939 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009940 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009941}
9942
Garfield Tane84e6f92019-08-29 17:28:41 -07009943} // namespace android::inputdispatcher