blob: 5c97b68ef59158b1754fe4e4989dd81e5d08e5b5 [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>
Ameer Armalycff4fa52023-10-04 23:45:11 +000027#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000028#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080030#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080031#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070033#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080035#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080038#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070039#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080040#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080041#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050044using android::gui::FocusRequest;
45using android::gui::TouchOcclusionMode;
46using android::gui::WindowInfo;
47using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080048using android::os::InputEventInjectionResult;
49using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080050
Garfield Tane84e6f92019-08-29 17:28:41 -070051namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
Dominik Laskowski2f01d772022-03-23 16:01:29 -070053using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080054using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070056namespace {
57
Michael Wrightd02c5b62014-02-10 15:10:22 -080058// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000059static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080060
61// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000062static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080063static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080064
Jeff Brownf086ddb2014-02-11 14:28:48 -080065// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000066static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
67static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080068
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000069// Ensure common actions are interchangeable between keys and motions for convenience.
70static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
71static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080072static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
73static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
74static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
75static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070076static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080077static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070078static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080079static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080080static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081/**
82 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
83 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
84 * index 0) is the new pointer going down. The same pointer could have been placed at a different
85 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
86 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
87 * pointer id=0 leaves but the pointer id=1 remains.
88 */
89static constexpr int32_t POINTER_0_DOWN =
90 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080091static constexpr int32_t POINTER_1_DOWN =
92 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000093static constexpr int32_t POINTER_2_DOWN =
94 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000095static constexpr int32_t POINTER_3_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000097static constexpr int32_t POINTER_0_UP =
98 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080099static constexpr int32_t POINTER_1_UP =
100 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000101static constexpr int32_t POINTER_2_UP =
102 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800103
Antonio Kantek15beb512022-06-13 22:35:41 +0000104// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000105static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000106static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000107
Antonio Kantek15beb512022-06-13 22:35:41 +0000108// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000109static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000110static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000111
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000112// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000113static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000114
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800115static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
116
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700117/**
118 * If we expect to receive the event, the timeout can be made very long. When the test are running
119 * correctly, we will actually never wait until the end of the timeout because the wait will end
120 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
121 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
122 * developer can see the failure quickly (on human scale).
123 */
124static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
125/**
126 * When no event is expected, we can have a very short timeout. A large value here would slow down
127 * the tests. In the unlikely event of system being too slow, the event may still be present but the
128 * timeout would complete before it is consumed. This would result in test flakiness. If this
129 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
130 * would get noticed and addressed quickly.
131 */
132static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
133
Arthur Hungc539dbb2022-12-08 07:45:36 +0000134static constexpr int expectedWallpaperFlags =
135 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
136
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800137using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
138
chaviwd1c23182019-12-20 18:44:56 -0800139struct PointF {
140 float x;
141 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800142 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800143};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800144
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700145inline std::string pointFToString(const PointF& p) {
146 return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
147}
148
Gang Wang342c9272020-01-13 13:15:04 -0500149/**
150 * Return a DOWN key event with KEYCODE_A.
151 */
152static KeyEvent getTestKeyEvent() {
153 KeyEvent event;
154
Garfield Tanfbe732e2020-01-24 11:26:14 -0800155 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
156 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
157 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500158 return event;
159}
160
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800161MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700162 *result_listener << "expected downTime " << downTime << ", but got " << arg.getDownTime();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800163 return arg.getDownTime() == downTime;
164}
165
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800166MATCHER_P(WithSource, source, "InputEvent with specified source") {
167 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
168 << inputEventSourceToString(arg.getSource());
169 return arg.getSource() == source;
170}
171
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800172MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700173 *result_listener << "expected flags " << std::hex << flags << ", but got " << arg.getFlags();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800174 return arg.getFlags() == flags;
175}
176
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800177MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
178 if (arg.getPointerCount() != 1) {
179 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
180 return false;
181 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700182 const float receivedX = arg.getX(/*pointerIndex=*/0);
183 const float receivedY = arg.getY(/*pointerIndex=*/0);
184 *result_listener << "expected coords (" << x << ", " << y << "), but got (" << receivedX << ", "
185 << receivedY << ")";
186 return receivedX == x && receivedY == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800187}
188
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800189MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700190 *result_listener << "expected pointerCount " << pointerCount << ", but got "
191 << arg.getPointerCount();
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800192 return arg.getPointerCount() == pointerCount;
193}
194
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800195MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
196 // Build a map for the received pointers, by pointer id
197 std::map<int32_t /*pointerId*/, PointF> actualPointers;
198 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
199 const int32_t pointerId = arg.getPointerId(pointerIndex);
200 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
201 }
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700202 *result_listener << "expected pointers " << dumpMap(pointers, constToString, pointFToString)
203 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800204 return pointers == actualPointers;
205}
206
Michael Wrightd02c5b62014-02-10 15:10:22 -0800207// --- FakeInputDispatcherPolicy ---
208
209class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000210 struct AnrResult {
211 sp<IBinder> token{};
212 gui::Pid pid{gui::Pid::INVALID};
213 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800214
Michael Wrightd02c5b62014-02-10 15:10:22 -0800215public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000216 FakeInputDispatcherPolicy() = default;
217 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800218
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800219 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700220 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700221 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700222 EXPECT_EQ(event.getDisplayId(), args.displayId);
223
224 const auto& keyEvent = static_cast<const KeyEvent&>(event);
225 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
226 EXPECT_EQ(keyEvent.getAction(), args.action);
227 });
Jackal Guof9696682018-10-05 12:23:23 +0800228 }
229
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700230 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
231 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700232 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700233 EXPECT_EQ(event.getDisplayId(), args.displayId);
234
235 const auto& motionEvent = static_cast<const MotionEvent&>(event);
236 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
237 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000238 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
240 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
241 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700242 });
Jackal Guof9696682018-10-05 12:23:23 +0800243 }
244
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700245 void assertFilterInputEventWasNotCalled() {
246 std::scoped_lock lock(mLock);
247 ASSERT_EQ(nullptr, mFilteredEvent);
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800250 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700251 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800252 ASSERT_TRUE(mConfigurationChangedTime)
253 << "Timed out waiting for configuration changed call";
254 ASSERT_EQ(*mConfigurationChangedTime, when);
255 mConfigurationChangedTime = std::nullopt;
256 }
257
258 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700259 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800260 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800261 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800262 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
263 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
264 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
265 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
266 mLastNotifySwitch = std::nullopt;
267 }
268
chaviwfd6d3512019-03-25 13:23:49 -0700269 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700270 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800271 ASSERT_EQ(touchedToken, mOnPointerDownToken);
272 mOnPointerDownToken.clear();
273 }
274
275 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700276 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800277 ASSERT_TRUE(mOnPointerDownToken == nullptr)
278 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700279 }
280
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700281 // This function must be called soon after the expected ANR timer starts,
282 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700284 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500285 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800286 std::unique_lock lock(mLock);
287 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500288 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800289 ASSERT_NO_FATAL_FAILURE(
290 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500291 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700292 }
293
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000294 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800295 const sp<WindowInfoHandle>& window) {
296 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
297 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
298 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500299 }
300
Prabir Pradhanedd96402022-02-15 01:46:16 -0800301 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
302 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000303 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800304 std::unique_lock lock(mLock);
305 android::base::ScopedLockAssertion assumeLocked(mLock);
306 AnrResult result;
307 ASSERT_NO_FATAL_FAILURE(result =
308 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000309 ASSERT_EQ(expectedToken, result.token);
310 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500311 }
312
Prabir Pradhanedd96402022-02-15 01:46:16 -0800313 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000314 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500315 std::unique_lock lock(mLock);
316 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800317 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
318 const auto& [token, _] = result;
319 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000320 }
321
Prabir Pradhanedd96402022-02-15 01:46:16 -0800322 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000323 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800324 std::unique_lock lock(mLock);
325 android::base::ScopedLockAssertion assumeLocked(mLock);
326 AnrResult result;
327 ASSERT_NO_FATAL_FAILURE(
328 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000329 ASSERT_EQ(expectedToken, result.token);
330 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800331 }
332
333 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000334 sp<IBinder> getResponsiveWindowToken() {
335 std::unique_lock lock(mLock);
336 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800337 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
338 const auto& [token, _] = result;
339 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700340 }
341
342 void assertNotifyAnrWasNotCalled() {
343 std::scoped_lock lock(mLock);
344 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800345 ASSERT_TRUE(mAnrWindows.empty());
346 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500347 << "ANR was not called, but please also consume the 'connection is responsive' "
348 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700349 }
350
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000351 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800352 std::unique_lock lock(mLock);
353 base::ScopedLockAssertion assumeLocked(mLock);
354
355 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
356 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000357 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800358 enabled;
359 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000360 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
361 << ") to be called.";
362 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000364 auto request = *mPointerCaptureRequest;
365 mPointerCaptureRequest.reset();
366 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800367 }
368
369 void assertSetPointerCaptureNotCalled() {
370 std::unique_lock lock(mLock);
371 base::ScopedLockAssertion assumeLocked(mLock);
372
373 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000378 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800379 }
380
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700381 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
382 const sp<IBinder>& targetToken) {
383 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800384 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800386 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800387 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800388 }
389
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800390 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
391 std::unique_lock lock(mLock);
392 base::ScopedLockAssertion assumeLocked(mLock);
393 std::optional<sp<IBinder>> receivedToken =
394 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
395 mNotifyInputChannelBroken);
396 ASSERT_TRUE(receivedToken.has_value());
397 ASSERT_EQ(token, *receivedToken);
398 }
399
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800400 /**
401 * Set policy timeout. A value of zero means next key will not be intercepted.
402 */
403 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
404 mInterceptKeyTimeout = timeout;
405 }
406
Josep del Riob3981622023-04-18 15:49:45 +0000407 void assertUserActivityPoked() {
408 std::scoped_lock lock(mLock);
409 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
410 }
411
412 void assertUserActivityNotPoked() {
413 std::scoped_lock lock(mLock);
414 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
415 }
416
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000417 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000418 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
419 }
420
421 void assertNotifyDeviceInteractionWasNotCalled() {
422 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
423 }
424
Michael Wrightd02c5b62014-02-10 15:10:22 -0800425private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700426 std::mutex mLock;
427 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
428 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
429 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
430 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800431
Prabir Pradhan99987712020-11-10 18:43:05 -0800432 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000433
434 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800435
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700436 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700437 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800438 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
439 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700440 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800441 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
442 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700443
arthurhungf452d0b2021-01-06 00:19:52 +0800444 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800445 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000446 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800447
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800448 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
449
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000450 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000451
Prabir Pradhanedd96402022-02-15 01:46:16 -0800452 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
453 // for a specific container to become non-empty. When the container is non-empty, return the
454 // first entry from the container and erase it.
455 template <class T>
456 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
457 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
458 // If there is an ANR, Dispatcher won't be idle because there are still events
459 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
460 // before checking if ANR was called.
461 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
462 // to provide it some time to act. 100ms seems reasonable.
463 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
464 const std::chrono::time_point start = std::chrono::steady_clock::now();
465 std::optional<T> token =
466 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
467 if (!token.has_value()) {
468 ADD_FAILURE() << "Did not receive the ANR callback";
469 return {};
470 }
471
472 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
473 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
474 // the dispatcher started counting before this function was called
475 if (std::chrono::abs(timeout - waited) > 100ms) {
476 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
477 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
478 << "ms, but waited "
479 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
480 << "ms instead";
481 }
482 return *token;
483 }
484
485 template <class T>
486 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
487 std::queue<T>& storage,
488 std::unique_lock<std::mutex>& lock,
489 std::condition_variable& condition)
490 REQUIRES(mLock) {
491 condition.wait_for(lock, timeout,
492 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
493 if (storage.empty()) {
494 ADD_FAILURE() << "Did not receive the expected callback";
495 return std::nullopt;
496 }
497 T item = storage.front();
498 storage.pop();
499 return std::make_optional(item);
500 }
501
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600502 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700503 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800504 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 }
506
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000507 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800508 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700509 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800510 ASSERT_TRUE(pid.has_value());
511 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700512 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500513 }
514
Prabir Pradhanedd96402022-02-15 01:46:16 -0800515 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000516 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500517 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800518 ASSERT_TRUE(pid.has_value());
519 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500520 mNotifyAnr.notify_all();
521 }
522
523 void notifyNoFocusedWindowAnr(
524 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
525 std::scoped_lock lock(mLock);
526 mAnrApplications.push(applicationHandle);
527 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800528 }
529
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800530 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
531 std::scoped_lock lock(mLock);
532 mBrokenInputChannels.push(connectionToken);
533 mNotifyInputChannelBroken.notify_all();
534 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800535
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600536 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700537
Chris Yef59a2f42020-10-16 12:55:26 -0700538 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
539 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
540 const std::vector<float>& values) override {}
541
542 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
543 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000544
Chris Yefb552902021-02-03 17:18:37 -0800545 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
546
Prabir Pradhana41d2442023-04-20 21:30:40 +0000547 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700548 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000549 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700550 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000551 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
552 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800553 break;
554 }
555
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700556 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000557 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
558 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800559 break;
560 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700561 default: {
562 ADD_FAILURE() << "Should only filter keys or motions";
563 break;
564 }
Jackal Guof9696682018-10-05 12:23:23 +0800565 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800566 return true;
567 }
568
Prabir Pradhana41d2442023-04-20 21:30:40 +0000569 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
570 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800571 // Clear intercept state when we handled the event.
572 mInterceptKeyTimeout = 0ms;
573 }
574 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800575
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600576 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577
Prabir Pradhana41d2442023-04-20 21:30:40 +0000578 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800579 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
580 // Clear intercept state so we could dispatch the event in next wake.
581 mInterceptKeyTimeout = 0ms;
582 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583 }
584
Prabir Pradhana41d2442023-04-20 21:30:40 +0000585 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
586 uint32_t) override {
587 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800588 }
589
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600590 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
591 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700592 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800593 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
594 * essentially a passthrough for notifySwitch.
595 */
Harry Cutts33476232023-01-30 19:57:29 +0000596 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800597 }
598
Josep del Riob3981622023-04-18 15:49:45 +0000599 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
600 std::scoped_lock lock(mLock);
601 mPokedUserActivity = true;
602 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800603
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600604 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700605 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700606 mOnPointerDownToken = newToken;
607 }
608
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000609 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800610 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000611 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800612 mPointerCaptureChangedCondition.notify_all();
613 }
614
arthurhungf452d0b2021-01-06 00:19:52 +0800615 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
616 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800617 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800618 mDropTargetWindowToken = token;
619 }
620
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000621 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000622 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000623 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
624 }
625
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700626 void assertFilterInputEventWasCalledInternal(
627 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700628 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800629 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700630 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800631 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800632 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700634} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800635
Michael Wrightd02c5b62014-02-10 15:10:22 -0800636// --- InputDispatcherTest ---
637
638class InputDispatcherTest : public testing::Test {
639protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000640 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700641 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800642
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000643 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000644 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
645 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000646 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000647 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700648 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800649 }
650
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000651 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700652 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000653 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700654 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800655 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700656
657 /**
658 * Used for debugging when writing the test
659 */
660 void dumpDispatcherState() {
661 std::string dump;
662 mDispatcher->dump(dump);
663 std::stringstream ss(dump);
664 std::string to;
665
666 while (std::getline(ss, to, '\n')) {
667 ALOGE("%s", to.c_str());
668 }
669 }
Vishnu Nair958da932020-08-21 17:12:37 -0700670
Chavi Weingarten847e8512023-03-29 00:26:09 +0000671 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700672 FocusRequest request;
673 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000674 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700675 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
676 request.displayId = window->getInfo()->displayId;
677 mDispatcher->setFocusedWindow(request);
678 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679};
680
Michael Wrightd02c5b62014-02-10 15:10:22 -0800681TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
682 KeyEvent event;
683
684 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800685 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
686 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000687 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600688 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800689 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000690 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000691 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800692 << "Should reject key events with undefined action.";
693
694 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800695 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
696 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600697 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800698 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000699 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000700 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800701 << "Should reject key events with ACTION_MULTIPLE.";
702}
703
704TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
705 MotionEvent event;
706 PointerProperties pointerProperties[MAX_POINTERS + 1];
707 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800708 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800709 pointerProperties[i].clear();
710 pointerProperties[i].id = i;
711 pointerCoords[i].clear();
712 }
713
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800714 // Some constants commonly used below
715 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
716 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
717 constexpr int32_t metaState = AMETA_NONE;
718 constexpr MotionClassification classification = MotionClassification::NONE;
719
chaviw9eaa22c2020-07-01 16:21:27 -0700720 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800721 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800722 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000723 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700724 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700725 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
726 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000727 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800728 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000729 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000730 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800731 << "Should reject motion events with undefined action.";
732
733 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800734 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800735 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
736 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
737 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
738 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000739 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800740 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000741 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000742 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800743 << "Should reject motion events with pointer down index too large.";
744
Garfield Tanfbe732e2020-01-24 11:26:14 -0800745 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700746 AMOTION_EVENT_ACTION_POINTER_DOWN |
747 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700748 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
749 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700750 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000751 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800752 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000753 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000754 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800755 << "Should reject motion events with pointer down index too small.";
756
757 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800758 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800759 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
760 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
761 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
762 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000763 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800764 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000765 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000766 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800767 << "Should reject motion events with pointer up index too large.";
768
Garfield Tanfbe732e2020-01-24 11:26:14 -0800769 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700770 AMOTION_EVENT_ACTION_POINTER_UP |
771 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700772 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
773 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700774 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000775 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800776 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000777 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000778 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800779 << "Should reject motion events with pointer up index too small.";
780
781 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800782 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
783 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700784 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700785 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
786 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000787 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800788 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000789 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000790 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800791 << "Should reject motion events with 0 pointers.";
792
Garfield Tanfbe732e2020-01-24 11:26:14 -0800793 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
794 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700795 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700796 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
797 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000798 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800799 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000800 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000801 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800802 << "Should reject motion events with more than MAX_POINTERS pointers.";
803
804 // Rejects motion events with invalid pointer ids.
805 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800806 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
807 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700808 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700809 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
810 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000811 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800812 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000813 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000814 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800815 << "Should reject motion events with pointer ids less than 0.";
816
817 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800818 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
819 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700820 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700821 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
822 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000823 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800824 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000825 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000826 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800827 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
828
829 // Rejects motion events with duplicate pointer ids.
830 pointerProperties[0].id = 1;
831 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800832 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
833 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700834 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700835 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
836 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000837 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800838 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000839 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000840 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800841 << "Should reject motion events with duplicate pointer ids.";
842}
843
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800844/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
845
846TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
847 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000848 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800849 ASSERT_TRUE(mDispatcher->waitForIdle());
850
851 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
852}
853
854TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000855 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
856 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000857 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800858
859 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
860 args.policyFlags |= POLICY_FLAG_TRUSTED;
861 mFakePolicy->assertNotifySwitchWasCalled(args);
862}
863
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700864namespace {
865
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700866static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700867// Default input dispatching timeout if there is no focused application or paused window
868// from which to determine an appropriate dispatching timeout.
869static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
870 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
871 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800872
873class FakeApplicationHandle : public InputApplicationHandle {
874public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700875 FakeApplicationHandle() {
876 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700877 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500878 mInfo.dispatchingTimeoutMillis =
879 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800881 virtual ~FakeApplicationHandle() {}
882
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000883 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500885 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
886 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700887 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800888};
889
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800890class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800891public:
Garfield Tan15601662020-09-22 15:32:38 -0700892 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800893 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700894 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800895 }
896
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700897 InputEvent* consume(std::chrono::milliseconds timeout) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700898 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700899 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700900 if (!consumeSeq) {
901 return nullptr;
902 }
903 finishEvent(*consumeSeq);
904 return event;
905 }
906
907 /**
908 * Receive an event without acknowledging it.
909 * Return the sequence number that could later be used to send finished signal.
910 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700911 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
912 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800913 uint32_t consumeSeq;
914 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800915
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800916 std::chrono::time_point start = std::chrono::steady_clock::now();
917 status_t status = WOULD_BLOCK;
918 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000919 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 &event);
921 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700922 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800923 break;
924 }
925 }
926
927 if (status == WOULD_BLOCK) {
928 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700929 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930 }
931
932 if (status != OK) {
933 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700934 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800935 }
936 if (event == nullptr) {
937 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800939 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700940 if (outEvent != nullptr) {
941 *outEvent = event;
942 }
943 return consumeSeq;
944 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800945
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700946 /**
947 * To be used together with "receiveEvent" to complete the consumption of an event.
948 */
949 void finishEvent(uint32_t consumeSeq) {
950 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
951 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800952 }
953
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000954 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
955 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
956 ASSERT_EQ(OK, status);
957 }
958
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700959 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000960 std::optional<int32_t> expectedDisplayId,
961 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700962 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800963
964 ASSERT_NE(nullptr, event) << mName.c_str()
965 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800966 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700967 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
968 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800969
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000970 if (expectedDisplayId.has_value()) {
971 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
972 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800973
Tiger Huang8664f8c2018-10-11 19:14:35 +0800974 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700975 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800976 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700977 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000978 if (expectedFlags.has_value()) {
979 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
980 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800981 break;
982 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700983 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800984 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700985 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000986 if (expectedFlags.has_value()) {
987 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
988 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800989 break;
990 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700991 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100992 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
993 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700994 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800995 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
996 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000998 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
999 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001001 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1002 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001003 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001004 }
1005
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001006 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001007 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001008
1009 if (event == nullptr) {
1010 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1011 return nullptr;
1012 }
1013
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001014 if (event->getType() != InputEventType::MOTION) {
1015 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001016 return nullptr;
1017 }
1018 return static_cast<MotionEvent*>(event);
1019 }
1020
1021 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1022 MotionEvent* motionEvent = consumeMotion();
1023 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1024 ASSERT_THAT(*motionEvent, matcher);
1025 }
1026
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001027 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001028 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001029 ASSERT_NE(nullptr, event) << mName.c_str()
1030 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001031 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1032 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001033
1034 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1035 << mName.c_str() << ": event displayId should always be NONE.";
1036
1037 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1038 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001039 }
1040
Prabir Pradhan99987712020-11-10 18:43:05 -08001041 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001042 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001043 ASSERT_NE(nullptr, event) << mName.c_str()
1044 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001045 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1046 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001047
1048 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1049 << mName.c_str() << ": event displayId should always be NONE.";
1050
1051 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1052 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1053 }
1054
arthurhungb89ccb02020-12-30 16:19:01 +08001055 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001056 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001057 ASSERT_NE(nullptr, event) << mName.c_str()
1058 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001059 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001060
1061 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1062 << mName.c_str() << ": event displayId should always be NONE.";
1063
1064 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1065 EXPECT_EQ(isExiting, dragEvent.isExiting());
1066 EXPECT_EQ(x, dragEvent.getX());
1067 EXPECT_EQ(y, dragEvent.getY());
1068 }
1069
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001071 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001072 ASSERT_NE(nullptr, event) << mName.c_str()
1073 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001074 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1075 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001076
1077 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1078 << mName.c_str() << ": event displayId should always be NONE.";
1079 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1080 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1081 }
1082
chaviwd1c23182019-12-20 18:44:56 -08001083 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001084 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001085 if (event == nullptr) {
1086 return;
1087 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001088 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001089 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1090 ADD_FAILURE() << "Received key event "
1091 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001092 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001093 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1094 ADD_FAILURE() << "Received motion event "
1095 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001096 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001097 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1098 ADD_FAILURE() << "Received focus event, hasFocus = "
1099 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001100 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001101 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1102 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1103 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001104 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001105 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1106 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1107 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001108 }
1109 FAIL() << mName.c_str()
1110 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001111 }
1112
1113 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1114
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001115 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1116
chaviwd1c23182019-12-20 18:44:56 -08001117protected:
1118 std::unique_ptr<InputConsumer> mConsumer;
1119 PreallocatedInputEventFactory mEventFactory;
1120
1121 std::string mName;
1122};
1123
chaviw3277faf2021-05-19 16:45:23 -05001124class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001125public:
1126 static const int32_t WIDTH = 600;
1127 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001128
Chris Yea209fde2020-07-22 13:54:51 -07001129 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001130 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001131 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001132 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001133 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001134 base::Result<std::unique_ptr<InputChannel>> channel =
1135 dispatcher->createInputChannel(name);
1136 token = (*channel)->getConnectionToken();
1137 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001138 }
1139
1140 inputApplicationHandle->updateInfo();
1141 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1142
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001143 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001144 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001145 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001146 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001147 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001148 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001149 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001150 mInfo.globalScaleFactor = 1.0;
1151 mInfo.touchableRegion.clear();
1152 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001153 mInfo.ownerPid = WINDOW_PID;
1154 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001155 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001156 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001157 }
1158
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001159 sp<FakeWindowHandle> clone(int32_t displayId) {
1160 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1161 handle->mInfo = mInfo;
1162 handle->mInfo.displayId = displayId;
1163 handle->mInfo.id = sId++;
1164 handle->mInputReceiver = mInputReceiver;
1165 return handle;
1166 }
1167
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001168 void setTouchable(bool touchable) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1170 }
chaviwd1c23182019-12-20 18:44:56 -08001171
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001172 void setFocusable(bool focusable) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1174 }
1175
1176 void setVisible(bool visible) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1178 }
Vishnu Nair958da932020-08-21 17:12:37 -07001179
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001180 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001181 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001182 }
1183
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001184 void setPaused(bool paused) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1186 }
1187
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001188 void setPreventSplitting(bool preventSplitting) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001190 }
1191
1192 void setSlippery(bool slippery) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1194 }
1195
1196 void setWatchOutsideTouch(bool watchOutside) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1198 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001199
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001200 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1201
1202 void setInterceptsStylus(bool interceptsStylus) {
1203 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1204 }
1205
1206 void setDropInput(bool dropInput) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1208 }
1209
1210 void setDropInputIfObscured(bool dropInputIfObscured) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1212 }
1213
1214 void setNoInputChannel(bool noInputChannel) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1216 }
1217
Josep del Riob3981622023-04-18 15:49:45 +00001218 void setDisableUserActivity(bool disableUserActivity) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1220 }
1221
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001222 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1223
chaviw3277faf2021-05-19 16:45:23 -05001224 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001225
Bernardo Rufino7393d172021-02-26 13:56:11 +00001226 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1227
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001228 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001229 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001230 mInfo.touchableRegion.clear();
1231 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001232
1233 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1234 ui::Transform translate;
1235 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1236 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001237 }
1238
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001239 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1240
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001241 void setIsWallpaper(bool isWallpaper) {
1242 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1243 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001244
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001245 void setDupTouchToWallpaper(bool hasWallpaper) {
1246 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1247 }
chaviwd1c23182019-12-20 18:44:56 -08001248
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001249 void setTrustedOverlay(bool trustedOverlay) {
1250 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1251 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001252
chaviw9eaa22c2020-07-01 16:21:27 -07001253 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1254 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1255 }
1256
1257 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001258
yunho.shinf4a80b82020-11-16 21:13:57 +09001259 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1260
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001261 KeyEvent* consumeKey() {
1262 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1263 if (event == nullptr) {
1264 ADD_FAILURE() << "Consume failed : no event";
1265 return nullptr;
1266 }
1267 if (event->getType() != InputEventType::KEY) {
1268 ADD_FAILURE() << "Instead of key event, got " << *event;
1269 return nullptr;
1270 }
1271 return static_cast<KeyEvent*>(event);
1272 }
1273
1274 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
1275 KeyEvent* keyEvent = consumeKey();
1276 ASSERT_NE(nullptr, keyEvent) << "Did not get a key event, but expected " << matcher;
1277 ASSERT_THAT(*keyEvent, matcher);
1278 }
1279
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001281 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001282 }
1283
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001284 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001285 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001286 }
1287
Svet Ganov5d3bc372020-01-26 23:11:07 -08001288 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001289 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001290 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1291 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001292 }
1293
1294 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001295 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001296 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1297 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001298 }
1299
1300 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001301 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001302 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1303 }
1304
1305 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1306 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001307 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001308 expectedFlags);
1309 }
1310
Svet Ganov5d3bc372020-01-26 23:11:07 -08001311 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1313 int32_t expectedFlags = 0) {
1314 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1315 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001316 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001317 }
1318
1319 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001320 int32_t expectedFlags = 0) {
1321 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1322 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001323 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001324 }
1325
1326 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001327 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001328 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001329 expectedFlags);
1330 }
1331
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001332 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1333 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001334 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001335 expectedFlags);
1336 }
1337
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001338 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1339 int32_t expectedFlags = 0) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001340 MotionEvent* motionEvent = consumeMotion();
1341 ASSERT_NE(nullptr, motionEvent);
1342 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent->getActionMasked());
1343 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getX());
1344 EXPECT_EQ(0.f, motionEvent->getRawPointerCoords(0)->getY());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001345 }
1346
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001347 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1348 ASSERT_NE(mInputReceiver, nullptr)
1349 << "Cannot consume events from a window with no receiver";
1350 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1351 }
1352
Prabir Pradhan99987712020-11-10 18:43:05 -08001353 void consumeCaptureEvent(bool hasCapture) {
1354 ASSERT_NE(mInputReceiver, nullptr)
1355 << "Cannot consume events from a window with no receiver";
1356 mInputReceiver->consumeCaptureEvent(hasCapture);
1357 }
1358
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001359 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1360 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001361 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001362 ASSERT_THAT(*motionEvent, matcher);
1363 }
1364
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001365 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001366 std::optional<int32_t> expectedDisplayId,
1367 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001368 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1369 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1370 expectedFlags);
1371 }
1372
arthurhungb89ccb02020-12-30 16:19:01 +08001373 void consumeDragEvent(bool isExiting, float x, float y) {
1374 mInputReceiver->consumeDragEvent(isExiting, x, y);
1375 }
1376
Antonio Kantekf16f2832021-09-28 04:39:20 +00001377 void consumeTouchModeEvent(bool inTouchMode) {
1378 ASSERT_NE(mInputReceiver, nullptr)
1379 << "Cannot consume events from a window with no receiver";
1380 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1381 }
1382
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001383 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001384 if (mInputReceiver == nullptr) {
1385 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1386 return std::nullopt;
1387 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001388 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001389 }
1390
1391 void finishEvent(uint32_t sequenceNum) {
1392 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1393 mInputReceiver->finishEvent(sequenceNum);
1394 }
1395
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001396 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1397 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1398 mInputReceiver->sendTimeline(inputEventId, timeline);
1399 }
1400
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001401 InputEvent* consume(std::chrono::milliseconds timeout) {
chaviwaf87b3e2019-10-01 16:59:28 -07001402 if (mInputReceiver == nullptr) {
1403 return nullptr;
1404 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001405 return mInputReceiver->consume(timeout);
chaviwaf87b3e2019-10-01 16:59:28 -07001406 }
1407
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001408 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001409 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001410 if (event == nullptr) {
1411 ADD_FAILURE() << "Consume failed : no event";
1412 return nullptr;
1413 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001414 if (event->getType() != InputEventType::MOTION) {
1415 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001416 return nullptr;
1417 }
1418 return static_cast<MotionEvent*>(event);
1419 }
1420
Arthur Hungb92218b2018-08-14 12:00:21 +08001421 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001422 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001423 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001424 return; // Can't receive events if the window does not have input channel
1425 }
1426 ASSERT_NE(nullptr, mInputReceiver)
1427 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001428 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001429 }
1430
chaviwaf87b3e2019-10-01 16:59:28 -07001431 sp<IBinder> getToken() { return mInfo.token; }
1432
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001433 const std::string& getName() { return mName; }
1434
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001435 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001436 mInfo.ownerPid = ownerPid;
1437 mInfo.ownerUid = ownerUid;
1438 }
1439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001440 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001441
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001442 void destroyReceiver() { mInputReceiver = nullptr; }
1443
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001444 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1445
chaviwd1c23182019-12-20 18:44:56 -08001446private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001447 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001448 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001449 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001450 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001451 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001452};
1453
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001454std::atomic<int32_t> FakeWindowHandle::sId{1};
1455
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001456static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001457 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001458 int32_t displayId = ADISPLAY_ID_NONE,
1459 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001460 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001461 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001462 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001463 KeyEvent event;
1464 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1465
1466 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001467 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001468 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1469 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001470
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001471 if (!allowKeyRepeat) {
1472 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1473 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001474 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001475 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001476}
1477
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001478static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1479 InputEventInjectionResult result =
1480 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1481 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1482 if (result != InputEventInjectionResult::TIMED_OUT) {
1483 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1484 }
1485}
1486
1487static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001488 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001489 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001490}
1491
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001492// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1493// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1494// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001495static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1496 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001497 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001498 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001499 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001500}
1501
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001502static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001503 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001504 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001505}
1506
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001507static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001508 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001509 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001510 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001511 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001512 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1513 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001514}
1515
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001516static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001517 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1518 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001519 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001520 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1521 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001522 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001523 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001524 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001525 MotionEventBuilder motionBuilder =
1526 MotionEventBuilder(action, source)
1527 .displayId(displayId)
1528 .eventTime(eventTime)
1529 .rawXCursorPosition(cursorPosition.x)
1530 .rawYCursorPosition(cursorPosition.y)
1531 .pointer(
1532 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1533 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1534 motionBuilder.downTime(eventTime);
1535 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001536
1537 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001538 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1539 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001540}
1541
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001542static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1543 int32_t displayId,
1544 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001545 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001546}
1547
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001548static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1549 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001550 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001551 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001552}
1553
Jackal Guof9696682018-10-05 12:23:23 +08001554static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1555 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1556 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001557 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001558 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1559 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001560
1561 return args;
1562}
1563
Josep del Riob3981622023-04-18 15:49:45 +00001564static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1565 int32_t displayId = ADISPLAY_ID_NONE) {
1566 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1567 // Define a valid key event.
1568 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001569 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001570 currentTime);
1571
1572 return args;
1573}
1574
1575static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1576 int32_t displayId = ADISPLAY_ID_NONE) {
1577 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1578 // Define a valid key event.
1579 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001580 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001581 AMETA_NONE, currentTime);
1582
1583 return args;
1584}
1585
Prabir Pradhan678438e2023-04-13 19:32:51 +00001586[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1587 int32_t displayId,
1588 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001589 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001590 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1591 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1592 }
1593
chaviwd1c23182019-12-20 18:44:56 -08001594 PointerProperties pointerProperties[pointerCount];
1595 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001596
chaviwd1c23182019-12-20 18:44:56 -08001597 for (size_t i = 0; i < pointerCount; i++) {
1598 pointerProperties[i].clear();
1599 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001600 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001601
chaviwd1c23182019-12-20 18:44:56 -08001602 pointerCoords[i].clear();
1603 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1604 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1605 }
Jackal Guof9696682018-10-05 12:23:23 +08001606
1607 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1608 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001609 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001610 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1611 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001612 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001613 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001614 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001615 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001616
1617 return args;
1618}
1619
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001620static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1621 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1622}
1623
chaviwd1c23182019-12-20 18:44:56 -08001624static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1625 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1626}
1627
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001628static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1629 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001630 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001631}
1632
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001633} // namespace
1634
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001635/**
1636 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1637 * broken channel.
1638 */
1639TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1640 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1641 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001642 sp<FakeWindowHandle>::make(application, mDispatcher,
1643 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001644
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001645 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001646
1647 // Window closes its channel, but the window remains.
1648 window->destroyReceiver();
1649 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1650}
1651
Arthur Hungb92218b2018-08-14 12:00:21 +08001652TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001654 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1655 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001656
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001657 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001659 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001661
1662 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001663 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001664}
1665
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001666TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001668 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1669 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001670
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001672 // Inject a MotionEvent to an unknown display.
1673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001674 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1676
1677 // Window should receive motion event.
1678 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1679}
1680
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001681/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001682 * Calling onWindowInfosChanged once should not cause any issues.
1683 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001684 * called twice.
1685 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001686TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1689 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001691
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001694 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697
1698 // Window should receive motion event.
1699 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1700}
1701
1702/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001703 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001704 */
1705TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001707 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1708 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001709 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001714 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717
1718 // Window should receive motion event.
1719 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1720}
1721
Arthur Hungb92218b2018-08-14 12:00:21 +08001722// The foreground window should receive the first touch down event.
1723TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001725 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001726 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001727 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001728 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001729
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001730 mDispatcher->onWindowInfosChanged(
1731 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001733 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001735
1736 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001737 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001738 windowSecond->assertNoEvents();
1739}
1740
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001741/**
1742 * Two windows: A top window, and a wallpaper behind the window.
1743 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1744 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001745 * 1. foregroundWindow <-- dup touch to wallpaper
1746 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001747 */
1748TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1750 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001751 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001752 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001753 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001754 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001755 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001757 mDispatcher->onWindowInfosChanged(
1758 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001761 {100, 200}))
1762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1763
1764 // Both foreground window and its wallpaper should receive the touch down
1765 foregroundWindow->consumeMotionDown();
1766 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1767
1768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001769 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001770 ADISPLAY_ID_DEFAULT, {110, 200}))
1771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1772
1773 foregroundWindow->consumeMotionMove();
1774 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1775
1776 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001777 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001778 foregroundWindow->consumeMotionCancel();
1779 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1780 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1781}
1782
1783/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001784 * Two fingers down on the window, and lift off the first finger.
1785 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1786 * contains a single pointer.
1787 */
1788TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1790 sp<FakeWindowHandle> window =
1791 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1792
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001793 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001794 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1796 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1797 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001798 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001799 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1800 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1801 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1802 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001803 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001804 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1805 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1806 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1807 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001808 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1809 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1810 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1811
1812 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001813 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001814 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1815 window->consumeMotionEvent(
1816 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1817}
1818
1819/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001820 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1821 * with the following differences:
1822 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1823 * clean up the connection.
1824 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1825 * Ensure that there's no crash in the dispatcher.
1826 */
1827TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1829 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001830 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001831 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001832 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001833 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001834 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001836 mDispatcher->onWindowInfosChanged(
1837 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001840 {100, 200}))
1841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1842
1843 // Both foreground window and its wallpaper should receive the touch down
1844 foregroundWindow->consumeMotionDown();
1845 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1846
1847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001848 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001849 ADISPLAY_ID_DEFAULT, {110, 200}))
1850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1851
1852 foregroundWindow->consumeMotionMove();
1853 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1854
1855 // Wallpaper closes its channel, but the window remains.
1856 wallpaperWindow->destroyReceiver();
1857 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1858
1859 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1860 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001861 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862 foregroundWindow->consumeMotionCancel();
1863}
1864
Arthur Hungc539dbb2022-12-08 07:45:36 +00001865class ShouldSplitTouchFixture : public InputDispatcherTest,
1866 public ::testing::WithParamInterface<bool> {};
1867INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1868 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001869/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870 * A single window that receives touch (on top), and a wallpaper window underneath it.
1871 * The top window gets a multitouch gesture.
1872 * Ensure that wallpaper gets the same gesture.
1873 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001874TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001876 sp<FakeWindowHandle> foregroundWindow =
1877 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1878 foregroundWindow->setDupTouchToWallpaper(true);
1879 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001880
1881 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001882 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001883 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001884
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001885 mDispatcher->onWindowInfosChanged(
1886 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001887
1888 // Touch down on top window
1889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001890 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 {100, 100}))
1892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1893
1894 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1897
1898 // Second finger down on the top window
1899 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001900 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001902 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1903 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 .build();
1905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001906 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 InputEventInjectionSync::WAIT_FOR_RESULT))
1908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1909
Harry Cutts33476232023-01-30 19:57:29 +00001910 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1911 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001913
1914 const MotionEvent secondFingerUpEvent =
1915 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1916 .displayId(ADISPLAY_ID_DEFAULT)
1917 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001918 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1919 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001920 .build();
1921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001922 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001923 InputEventInjectionSync::WAIT_FOR_RESULT))
1924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1925 foregroundWindow->consumeMotionPointerUp(0);
1926 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1927
1928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001929 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001930 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1931 AINPUT_SOURCE_TOUCHSCREEN)
1932 .displayId(ADISPLAY_ID_DEFAULT)
1933 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001934 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001935 .x(100)
1936 .y(100))
1937 .build(),
1938 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1940 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1941 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001942}
1943
1944/**
1945 * Two windows: a window on the left and window on the right.
1946 * A third window, wallpaper, is behind both windows, and spans both top windows.
1947 * The first touch down goes to the left window. A second pointer touches down on the right window.
1948 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1949 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1950 * ACTION_POINTER_DOWN(1).
1951 */
1952TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1954 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001955 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001957 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958
1959 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001960 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001961 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001962 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963
1964 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001965 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001966 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001967 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001969 mDispatcher->onWindowInfosChanged(
1970 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1971 {},
1972 0,
1973 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974
1975 // Touch down on left window
1976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001977 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978 {100, 100}))
1979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1980
1981 // Both foreground window and its wallpaper should receive the touch down
1982 leftWindow->consumeMotionDown();
1983 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1984
1985 // Second finger down on the right window
1986 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001987 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001989 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1990 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991 .build();
1992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001993 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001994 InputEventInjectionSync::WAIT_FOR_RESULT))
1995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1996
1997 leftWindow->consumeMotionMove();
1998 // Since the touch is split, right window gets ACTION_DOWN
1999 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002000 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002001 expectedWallpaperFlags);
2002
2003 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002004 mDispatcher->onWindowInfosChanged(
2005 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002006 leftWindow->consumeMotionCancel();
2007 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2008 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2009
2010 // The pointer that's still down on the right window moves, and goes to the right window only.
2011 // As far as the dispatcher's concerned though, both pointers are still present.
2012 const MotionEvent secondFingerMoveEvent =
2013 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2014 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002015 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2016 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017 .build();
2018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002019 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020 InputEventInjectionSync::WAIT_FOR_RESULT));
2021 rightWindow->consumeMotionMove();
2022
2023 leftWindow->assertNoEvents();
2024 rightWindow->assertNoEvents();
2025 wallpaperWindow->assertNoEvents();
2026}
2027
Arthur Hungc539dbb2022-12-08 07:45:36 +00002028/**
2029 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2030 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2031 * The right window should receive ACTION_DOWN.
2032 */
2033TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002035 sp<FakeWindowHandle> leftWindow =
2036 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2037 leftWindow->setFrame(Rect(0, 0, 200, 200));
2038 leftWindow->setDupTouchToWallpaper(true);
2039 leftWindow->setSlippery(true);
2040
2041 sp<FakeWindowHandle> rightWindow =
2042 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2043 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002044
2045 sp<FakeWindowHandle> wallpaperWindow =
2046 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2047 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002048
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002049 mDispatcher->onWindowInfosChanged(
2050 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2051 {},
2052 0,
2053 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002054
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002057 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002058 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002060
2061 // Both foreground window and its wallpaper should receive the touch down
2062 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002063 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2064
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002067 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2070
Arthur Hungc539dbb2022-12-08 07:45:36 +00002071 leftWindow->consumeMotionCancel();
2072 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2073 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002074}
2075
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002076/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002077 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2078 * interactive, it might stop sending this flag.
2079 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2080 * to have a consistent input stream.
2081 *
2082 * Test procedure:
2083 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2084 * DOWN (new gesture).
2085 *
2086 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2087 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2088 *
2089 * We technically just need a single window here, but we are using two windows (spy on top and a
2090 * regular window below) to emulate the actual situation where it happens on the device.
2091 */
2092TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2093 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2094 sp<FakeWindowHandle> spyWindow =
2095 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2096 spyWindow->setFrame(Rect(0, 0, 200, 200));
2097 spyWindow->setTrustedOverlay(true);
2098 spyWindow->setSpy(true);
2099
2100 sp<FakeWindowHandle> window =
2101 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2102 window->setFrame(Rect(0, 0, 200, 200));
2103
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002104 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002105 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106
2107 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002108 mDispatcher->notifyMotion(
2109 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2110 .deviceId(touchDeviceId)
2111 .policyFlags(DEFAULT_POLICY_FLAGS)
2112 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2113 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002114
Prabir Pradhan678438e2023-04-13 19:32:51 +00002115 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2116 .deviceId(touchDeviceId)
2117 .policyFlags(DEFAULT_POLICY_FLAGS)
2118 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2119 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2120 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002121 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2122 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2123 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2124 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2125
2126 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002127 mDispatcher->notifyMotion(
2128 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2129 .deviceId(touchDeviceId)
2130 .policyFlags(0)
2131 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2132 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2133 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2135 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2136
2137 // We don't need to reset the device to reproduce the issue, but the reset event typically
2138 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002139 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002140
2141 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002142 mDispatcher->notifyMotion(
2143 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2144 .deviceId(touchDeviceId)
2145 .policyFlags(DEFAULT_POLICY_FLAGS)
2146 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2147 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002148 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2149 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2150
2151 // No more events
2152 spyWindow->assertNoEvents();
2153 window->assertNoEvents();
2154}
2155
2156/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002157 * Two windows: a window on the left and a window on the right.
2158 * Mouse is hovered from the right window into the left window.
2159 * Next, we tap on the left window, where the cursor was last seen.
2160 * The second tap is done onto the right window.
2161 * The mouse and tap are from two different devices.
2162 * We technically don't need to set the downtime / eventtime for these events, but setting these
2163 * explicitly helps during debugging.
2164 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2165 * In the buggy implementation, a tap on the right window would cause a crash.
2166 */
2167TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2169 sp<FakeWindowHandle> leftWindow =
2170 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2171 leftWindow->setFrame(Rect(0, 0, 200, 200));
2172
2173 sp<FakeWindowHandle> rightWindow =
2174 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2175 rightWindow->setFrame(Rect(200, 0, 400, 200));
2176
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002177 mDispatcher->onWindowInfosChanged(
2178 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002179 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2180 // stale.
2181 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2182 const int32_t mouseDeviceId = 6;
2183 const int32_t touchDeviceId = 4;
2184 // Move the cursor from right
2185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002186 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002187 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2188 AINPUT_SOURCE_MOUSE)
2189 .deviceId(mouseDeviceId)
2190 .downTime(baseTime + 10)
2191 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002192 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002193 .build()));
2194 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2195
2196 // .. to the left window
2197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002198 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002199 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2200 AINPUT_SOURCE_MOUSE)
2201 .deviceId(mouseDeviceId)
2202 .downTime(baseTime + 10)
2203 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002204 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002205 .build()));
2206 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2207 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2208 // Now tap the left window
2209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002210 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002211 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2212 AINPUT_SOURCE_TOUCHSCREEN)
2213 .deviceId(touchDeviceId)
2214 .downTime(baseTime + 40)
2215 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002216 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002217 .build()));
2218 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2219 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2220
2221 // release tap
2222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002223 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002224 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2225 AINPUT_SOURCE_TOUCHSCREEN)
2226 .deviceId(touchDeviceId)
2227 .downTime(baseTime + 40)
2228 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002229 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002230 .build()));
2231 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2232
2233 // Tap the window on the right
2234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002235 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002236 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2237 AINPUT_SOURCE_TOUCHSCREEN)
2238 .deviceId(touchDeviceId)
2239 .downTime(baseTime + 60)
2240 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002241 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002242 .build()));
2243 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2244
2245 // release tap
2246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2249 AINPUT_SOURCE_TOUCHSCREEN)
2250 .deviceId(touchDeviceId)
2251 .downTime(baseTime + 60)
2252 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002253 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002254 .build()));
2255 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2256
2257 // No more events
2258 leftWindow->assertNoEvents();
2259 rightWindow->assertNoEvents();
2260}
2261
2262/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002263 * Start hovering in a window. While this hover is still active, make another window appear on top.
2264 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2265 * While the top window is present, the hovering is stopped.
2266 * Later, hovering gets resumed again.
2267 * Ensure that new hover gesture is handled correctly.
2268 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2269 * to the window that's currently being hovered over.
2270 */
2271TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2273 sp<FakeWindowHandle> window =
2274 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2275 window->setFrame(Rect(0, 0, 200, 200));
2276
2277 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002278 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002279
2280 // Start hovering in the window
2281 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2282 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2283 .build());
2284 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2285
2286 // Now, an obscuring window appears!
2287 sp<FakeWindowHandle> obscuringWindow =
2288 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2289 ADISPLAY_ID_DEFAULT,
2290 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2291 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2292 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2293 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2294 obscuringWindow->setNoInputChannel(true);
2295 obscuringWindow->setFocusable(false);
2296 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002297 mDispatcher->onWindowInfosChanged(
2298 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002299
2300 // While this new obscuring window is present, the hovering is stopped
2301 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2302 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2303 .build());
2304 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2305
2306 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002307 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002308
2309 // And a new hover gesture starts.
2310 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2311 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2312 .build());
2313 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2314}
2315
2316/**
2317 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2318 * the obscuring window.
2319 */
2320TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2322 sp<FakeWindowHandle> window =
2323 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2324 window->setFrame(Rect(0, 0, 200, 200));
2325
2326 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002327 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002328
2329 // Start hovering in the window
2330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2332 .build());
2333 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2334
2335 // Now, an obscuring window appears!
2336 sp<FakeWindowHandle> obscuringWindow =
2337 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2338 ADISPLAY_ID_DEFAULT,
2339 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2340 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2341 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2342 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2343 obscuringWindow->setNoInputChannel(true);
2344 obscuringWindow->setFocusable(false);
2345 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002346 mDispatcher->onWindowInfosChanged(
2347 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002348
2349 // While this new obscuring window is present, the hovering continues. The event can't go to the
2350 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2351 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2352 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2353 .build());
2354 obscuringWindow->assertNoEvents();
2355 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2356
2357 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002358 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002359
2360 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2361 // so it should generate a HOVER_ENTER
2362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2363 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2364 .build());
2365 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2366
2367 // Now the MOVE should be getting dispatched normally
2368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2370 .build());
2371 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2372}
2373
2374/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002375 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2376 * events are delivered to the window.
2377 */
2378TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2380 sp<FakeWindowHandle> window =
2381 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2382 window->setFrame(Rect(0, 0, 200, 200));
2383 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2384
2385 // Start hovering in the window
2386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2387 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2388 .build());
2389 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2390
2391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2392 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2393 .build());
2394 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2395
2396 // Scroll with the mouse
2397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2398 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2399 .build());
2400 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2401}
2402
2403using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2404
2405/**
2406 * One window. Stylus down on the window. Next, touch from another device goes down.
2407 */
2408TEST_F(InputDispatcherMultiDeviceTest, StylusDownAndTouchDown) {
2409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2410 sp<FakeWindowHandle> window =
2411 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2412 window->setFrame(Rect(0, 0, 200, 200));
2413
2414 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2415
2416 constexpr int32_t touchDeviceId = 4;
2417 constexpr int32_t stylusDeviceId = 2;
2418
2419 // Stylus down
2420 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2421 .deviceId(stylusDeviceId)
2422 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2423 .build());
2424 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2425
2426 // Touch down
2427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2428 .deviceId(touchDeviceId)
2429 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2430 .build());
2431 // Touch cancels stylus
2432 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId),
2433 WithCoords(100, 110)));
2434 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId),
2435 WithCoords(140, 145)));
2436
2437 // Touch move
2438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2439 .deviceId(touchDeviceId)
2440 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2441 .build());
2442 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2443 WithCoords(141, 146)));
2444
2445 // Subsequent stylus movements are dropped
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2447 .deviceId(stylusDeviceId)
2448 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2449 .build());
2450 window->assertNoEvents();
2451}
2452
2453/**
2454 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2455 * down.
2456 * Similar test as above, but with added SPY window.
2457 */
2458TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyAndTouchDown) {
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 sp<FakeWindowHandle> spyWindow =
2463 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2464 spyWindow->setFrame(Rect(0, 0, 200, 200));
2465 spyWindow->setTrustedOverlay(true);
2466 spyWindow->setSpy(true);
2467 window->setFrame(Rect(0, 0, 200, 200));
2468
2469 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2470
2471 constexpr int32_t touchDeviceId = 4;
2472 constexpr int32_t stylusDeviceId = 2;
2473
2474 // Stylus down
2475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2476 .deviceId(stylusDeviceId)
2477 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2478 .build());
2479 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2480 spyWindow->consumeMotionEvent(
2481 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2482
2483 // Touch down
2484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2485 .deviceId(touchDeviceId)
2486 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2487 .build());
2488
2489 // Touch move
2490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2491 .deviceId(touchDeviceId)
2492 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2493 .build());
2494 window->consumeMotionEvent(
2495 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2496 spyWindow->consumeMotionEvent(
2497 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2498 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2499 spyWindow->consumeMotionEvent(
2500 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2501 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2502 spyWindow->consumeMotionEvent(
2503 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2504 // Subsequent stylus movements are dropped
2505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2506 .deviceId(stylusDeviceId)
2507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2508 .build());
2509
2510 window->assertNoEvents();
2511 spyWindow->assertNoEvents();
2512}
2513
2514/**
2515 * One window. Stylus hover on the window. Next, touch from another device goes down.
2516 */
2517TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchDown) {
2518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2519 sp<FakeWindowHandle> window =
2520 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2521 window->setFrame(Rect(0, 0, 200, 200));
2522
2523 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2524
2525 constexpr int32_t touchDeviceId = 4;
2526 constexpr int32_t stylusDeviceId = 2;
2527
2528 // Stylus down on the window
2529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2530 .deviceId(stylusDeviceId)
2531 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2532 .build());
2533 window->consumeMotionEvent(
2534 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2535
2536 // Touch down on window
2537 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2538 .deviceId(touchDeviceId)
2539 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2540 .build());
2541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2542 .deviceId(touchDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2544 .build());
2545 window->consumeMotionEvent(
2546 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2547 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2548 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2549 // Subsequent stylus movements are ignored
2550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2551 .deviceId(stylusDeviceId)
2552 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2553 .build());
2554 window->assertNoEvents();
2555}
2556
2557/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002558 * Two windows: a window on the left and a window on the right.
2559 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2560 * down. Then, on the left window, also place second touch pointer down.
2561 * This test tries to reproduce a crash.
2562 * In the buggy implementation, second pointer down on the left window would cause a crash.
2563 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002564TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2566 sp<FakeWindowHandle> leftWindow =
2567 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2568 leftWindow->setFrame(Rect(0, 0, 200, 200));
2569
2570 sp<FakeWindowHandle> rightWindow =
2571 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2572 rightWindow->setFrame(Rect(200, 0, 400, 200));
2573
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002574 mDispatcher->onWindowInfosChanged(
2575 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002576
2577 const int32_t touchDeviceId = 4;
2578 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002579
2580 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2582 .deviceId(mouseDeviceId)
2583 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2584 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002585 leftWindow->consumeMotionEvent(
2586 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2587
2588 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2590 .deviceId(mouseDeviceId)
2591 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2592 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2593 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002594
2595 leftWindow->consumeMotionEvent(
2596 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2597 leftWindow->consumeMotionEvent(
2598 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2599
Prabir Pradhan678438e2023-04-13 19:32:51 +00002600 mDispatcher->notifyMotion(
2601 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2602 .deviceId(mouseDeviceId)
2603 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2604 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2605 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2606 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002607 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2608
2609 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2611 .deviceId(touchDeviceId)
2612 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2613 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002614 leftWindow->consumeMotionEvent(
2615 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002616 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2617
2618 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002619 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2620 .deviceId(touchDeviceId)
2621 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2622 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2623 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002624 leftWindow->consumeMotionEvent(
2625 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2626 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2627 // current implementation.
2628 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2629 rightWindow->consumeMotionEvent(
2630 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2631
2632 leftWindow->assertNoEvents();
2633 rightWindow->assertNoEvents();
2634}
2635
2636/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002637 * Two windows: a window on the left and a window on the right.
2638 * Mouse is hovered on the left window and stylus is hovered on the right window.
2639 */
2640TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2641 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2642 sp<FakeWindowHandle> leftWindow =
2643 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2644 leftWindow->setFrame(Rect(0, 0, 200, 200));
2645
2646 sp<FakeWindowHandle> rightWindow =
2647 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2648 rightWindow->setFrame(Rect(200, 0, 400, 200));
2649
2650 mDispatcher->onWindowInfosChanged(
2651 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2652
2653 const int32_t stylusDeviceId = 3;
2654 const int32_t mouseDeviceId = 6;
2655
2656 // Start hovering over the left window
2657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2658 .deviceId(mouseDeviceId)
2659 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2660 .build());
2661 leftWindow->consumeMotionEvent(
2662 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2663
2664 // Stylus hovered on right window
2665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2666 .deviceId(stylusDeviceId)
2667 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2668 .build());
2669 leftWindow->consumeMotionEvent(
2670 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2671 rightWindow->consumeMotionEvent(
2672 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2673
2674 // Subsequent HOVER_MOVE events are dispatched correctly.
2675 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2676 .deviceId(mouseDeviceId)
2677 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2678 .build());
2679 leftWindow->consumeMotionEvent(
2680 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2681 rightWindow->consumeMotionEvent(
2682 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2683
2684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2685 .deviceId(stylusDeviceId)
2686 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2687 .build());
2688 leftWindow->consumeMotionEvent(
2689 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2690 rightWindow->consumeMotionEvent(
2691 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2692
2693 leftWindow->assertNoEvents();
2694 rightWindow->assertNoEvents();
2695}
2696
2697/**
2698 * Three windows: a window on the left and a window on the right.
2699 * And a spy window that's positioned above all of them.
2700 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2701 * Check the stream that's received by the spy.
2702 */
2703TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2705
2706 sp<FakeWindowHandle> spyWindow =
2707 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2708 spyWindow->setFrame(Rect(0, 0, 400, 400));
2709 spyWindow->setTrustedOverlay(true);
2710 spyWindow->setSpy(true);
2711
2712 sp<FakeWindowHandle> leftWindow =
2713 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2714 leftWindow->setFrame(Rect(0, 0, 200, 200));
2715
2716 sp<FakeWindowHandle> rightWindow =
2717 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2718
2719 rightWindow->setFrame(Rect(200, 0, 400, 200));
2720
2721 mDispatcher->onWindowInfosChanged(
2722 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2723
2724 const int32_t stylusDeviceId = 1;
2725 const int32_t touchDeviceId = 2;
2726
2727 // Stylus down on the left window
2728 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2729 .deviceId(stylusDeviceId)
2730 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2731 .build());
2732 leftWindow->consumeMotionEvent(
2733 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2734 spyWindow->consumeMotionEvent(
2735 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2736
2737 // Touch down on the right window
2738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2739 .deviceId(touchDeviceId)
2740 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2741 .build());
2742 leftWindow->consumeMotionEvent(
2743 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2744 spyWindow->consumeMotionEvent(
2745 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
2746 rightWindow->consumeMotionEvent(
2747 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2748 spyWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2750
2751 // Stylus movements continue, but are ignored because the touch went down more recently.
2752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2753 .deviceId(stylusDeviceId)
2754 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2755 .build());
2756
2757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2758 .deviceId(touchDeviceId)
2759 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2760 .build());
2761 rightWindow->consumeMotionEvent(
2762 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2763 spyWindow->consumeMotionEvent(
2764 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2765
2766 spyWindow->assertNoEvents();
2767 leftWindow->assertNoEvents();
2768 rightWindow->assertNoEvents();
2769}
2770
2771/**
2772 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2773 * both.
2774 * Check hover in left window and touch down in the right window.
2775 * At first, spy should receive hover, but the touch down should cancel hovering inside spy.
2776 */
2777TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverAndTouchWithSpy) {
2778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2779
2780 sp<FakeWindowHandle> spyWindow =
2781 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2782 spyWindow->setFrame(Rect(0, 0, 400, 400));
2783 spyWindow->setTrustedOverlay(true);
2784 spyWindow->setSpy(true);
2785
2786 sp<FakeWindowHandle> leftWindow =
2787 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2788 leftWindow->setFrame(Rect(0, 0, 200, 200));
2789
2790 sp<FakeWindowHandle> rightWindow =
2791 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2792 rightWindow->setFrame(Rect(200, 0, 400, 200));
2793
2794 mDispatcher->onWindowInfosChanged(
2795 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2796
2797 const int32_t stylusDeviceId = 1;
2798 const int32_t touchDeviceId = 2;
2799
2800 // Stylus hover on the left window
2801 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2802 .deviceId(stylusDeviceId)
2803 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2804 .build());
2805 leftWindow->consumeMotionEvent(
2806 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2807 spyWindow->consumeMotionEvent(
2808 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2809
2810 // Touch down on the right window.
2811 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2812 .deviceId(touchDeviceId)
2813 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2814 .build());
2815 leftWindow->consumeMotionEvent(
2816 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2817 spyWindow->consumeMotionEvent(
2818 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
2819 spyWindow->consumeMotionEvent(
2820 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2821 rightWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2823
2824 // Stylus movements continue, but are ignored because the touch is down.
2825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2826 .deviceId(stylusDeviceId)
2827 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2828 .build());
2829
2830 // Touch movements continue. They should be delivered to the right window and to the spy
2831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2832 .deviceId(touchDeviceId)
2833 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2834 .build());
2835 spyWindow->consumeMotionEvent(
2836 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2837 rightWindow->consumeMotionEvent(
2838 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2839
2840 spyWindow->assertNoEvents();
2841 leftWindow->assertNoEvents();
2842 rightWindow->assertNoEvents();
2843}
2844
2845/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002846 * On a single window, use two different devices: mouse and touch.
2847 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2848 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2849 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2850 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2851 * represent a new gesture.
2852 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002853TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2855 sp<FakeWindowHandle> window =
2856 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2857 window->setFrame(Rect(0, 0, 400, 400));
2858
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002859 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002860
2861 const int32_t touchDeviceId = 4;
2862 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002863
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002864 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2866 .deviceId(touchDeviceId)
2867 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2868 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002869 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002870 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2871 .deviceId(touchDeviceId)
2872 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2873 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2874 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002875 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2877 .deviceId(touchDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2879 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2880 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002881 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2882 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2883 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2884
2885 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2887 .deviceId(mouseDeviceId)
2888 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2889 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2890 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002891
2892 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002893 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002894 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2895
Prabir Pradhan678438e2023-04-13 19:32:51 +00002896 mDispatcher->notifyMotion(
2897 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2898 .deviceId(mouseDeviceId)
2899 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2900 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2901 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2902 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002903 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2904
2905 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002906 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2907 .deviceId(touchDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2909 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2910 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002911 // Since we already canceled this touch gesture, it will be ignored until a completely new
2912 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2913 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2914 // However, mouse movements should continue to work.
2915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2916 .deviceId(mouseDeviceId)
2917 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2918 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2919 .build());
2920 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2921
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002922 window->assertNoEvents();
2923}
2924
2925/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002926 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2927 * the injected event.
2928 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002929TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2931 sp<FakeWindowHandle> window =
2932 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2933 window->setFrame(Rect(0, 0, 400, 400));
2934
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002935 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002936
2937 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002938 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2939 // completion.
2940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002941 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002942 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2943 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002944 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002945 .build()));
2946 window->consumeMotionEvent(
2947 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2948
2949 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2950 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002951 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2952 .deviceId(touchDeviceId)
2953 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2954 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002955
2956 window->consumeMotionEvent(
2957 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2958 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2959}
2960
2961/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002962 * This test is similar to the test above, but the sequence of injected events is different.
2963 *
2964 * Two windows: a window on the left and a window on the right.
2965 * Mouse is hovered over the left window.
2966 * Next, we tap on the left window, where the cursor was last seen.
2967 *
2968 * After that, we inject one finger down onto the right window, and then a second finger down onto
2969 * the left window.
2970 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2971 * window (first), and then another on the left window (second).
2972 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2973 * In the buggy implementation, second finger down on the left window would cause a crash.
2974 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002975TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002976 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2977 sp<FakeWindowHandle> leftWindow =
2978 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2979 leftWindow->setFrame(Rect(0, 0, 200, 200));
2980
2981 sp<FakeWindowHandle> rightWindow =
2982 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2983 rightWindow->setFrame(Rect(200, 0, 400, 200));
2984
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002985 mDispatcher->onWindowInfosChanged(
2986 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002987
2988 const int32_t mouseDeviceId = 6;
2989 const int32_t touchDeviceId = 4;
2990 // Hover over the left window. Keep the cursor there.
2991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002992 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002993 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2994 AINPUT_SOURCE_MOUSE)
2995 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002996 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002997 .build()));
2998 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2999
3000 // Tap on left window
3001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003002 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003003 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3004 AINPUT_SOURCE_TOUCHSCREEN)
3005 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003006 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003007 .build()));
3008
3009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003010 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003011 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3012 AINPUT_SOURCE_TOUCHSCREEN)
3013 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003014 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003015 .build()));
3016 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3017 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3018 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3019
3020 // First finger down on right window
3021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003022 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003023 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3024 AINPUT_SOURCE_TOUCHSCREEN)
3025 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003026 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003027 .build()));
3028 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3029
3030 // Second finger down on the left window
3031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003032 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003033 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3034 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003035 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3036 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003037 .build()));
3038 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3039 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3040
3041 // No more events
3042 leftWindow->assertNoEvents();
3043 rightWindow->assertNoEvents();
3044}
3045
3046/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003047 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3048 * While the touch is down, new hover events from the stylus device should be ignored. After the
3049 * touch is gone, stylus hovering should start working again.
3050 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003051TEST_F(InputDispatcherMultiDeviceTest, StylusHoverAndTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3053 sp<FakeWindowHandle> window =
3054 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3055 window->setFrame(Rect(0, 0, 200, 200));
3056
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003057 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003058
3059 const int32_t stylusDeviceId = 5;
3060 const int32_t touchDeviceId = 4;
3061 // Start hovering with stylus
3062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003063 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003065 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003066 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003067 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003069
3070 // Finger down on the window
3071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003072 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003073 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003074 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003075 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003076 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003077 window->consumeMotionEvent(
3078 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3079 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003080
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003081 // Continue hovering with stylus. Injection will fail because touch is already down.
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003082 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003083 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003084 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3085 AINPUT_SOURCE_STYLUS)
3086 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003087 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003088 .build()));
3089 // No event should be sent. This event should be ignored because a pointer from another device
3090 // is already down.
3091
3092 // Lift up the finger
3093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003094 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003095 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3096 AINPUT_SOURCE_TOUCHSCREEN)
3097 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003098 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003099 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003100 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003101
3102 // Now that the touch is gone, stylus hovering should start working again
3103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003104 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003105 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3106 AINPUT_SOURCE_STYLUS)
3107 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003108 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003109 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003110 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3111 WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003112 window->assertNoEvents();
3113}
3114
3115/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003116 * A spy window above a window with no input channel.
3117 * Start hovering with a stylus device, and then tap with it.
3118 * Ensure spy window receives the entire sequence.
3119 */
3120TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3121 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3122 sp<FakeWindowHandle> spyWindow =
3123 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3124 spyWindow->setFrame(Rect(0, 0, 200, 200));
3125 spyWindow->setTrustedOverlay(true);
3126 spyWindow->setSpy(true);
3127 sp<FakeWindowHandle> window =
3128 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3129 window->setNoInputChannel(true);
3130 window->setFrame(Rect(0, 0, 200, 200));
3131
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003132 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003133
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003134 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003135 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3136 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3137 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003138 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3139 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003140 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3141 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3142 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003143 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3144
3145 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3147 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3148 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003149 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3150
3151 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3153 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3154 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3156
3157 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3159 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3160 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003161 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3162 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003163 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3164 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3165 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003166 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3167
3168 // No more events
3169 spyWindow->assertNoEvents();
3170 window->assertNoEvents();
3171}
3172
3173/**
3174 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3175 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3176 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3177 * While the mouse is down, new move events from the touch device should be ignored.
3178 */
3179TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3181 sp<FakeWindowHandle> spyWindow =
3182 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3183 spyWindow->setFrame(Rect(0, 0, 200, 200));
3184 spyWindow->setTrustedOverlay(true);
3185 spyWindow->setSpy(true);
3186 sp<FakeWindowHandle> window =
3187 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3188 window->setFrame(Rect(0, 0, 200, 200));
3189
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003190 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003191
3192 const int32_t mouseDeviceId = 7;
3193 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003194
3195 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3197 .deviceId(mouseDeviceId)
3198 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3199 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003200 spyWindow->consumeMotionEvent(
3201 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3202 window->consumeMotionEvent(
3203 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3204
3205 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3207 .deviceId(touchDeviceId)
3208 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3209 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003210 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3211 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3212 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3213 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3214
Prabir Pradhan678438e2023-04-13 19:32:51 +00003215 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3216 .deviceId(touchDeviceId)
3217 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3218 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003219 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3220 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3221
3222 // Pilfer the stream
3223 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3224 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3225
Prabir Pradhan678438e2023-04-13 19:32:51 +00003226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3227 .deviceId(touchDeviceId)
3228 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3229 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003230 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3231
3232 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3234 .deviceId(mouseDeviceId)
3235 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3236 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3237 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003238
3239 spyWindow->consumeMotionEvent(
3240 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3241 spyWindow->consumeMotionEvent(
3242 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3243 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3244
Prabir Pradhan678438e2023-04-13 19:32:51 +00003245 mDispatcher->notifyMotion(
3246 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3247 .deviceId(mouseDeviceId)
3248 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3249 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3250 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3251 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003252 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3253 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3254
3255 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003256 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3257 .deviceId(mouseDeviceId)
3258 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3259 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3260 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003261 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3262 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3263
3264 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3266 .deviceId(touchDeviceId)
3267 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3268 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003269
3270 // No more events
3271 spyWindow->assertNoEvents();
3272 window->assertNoEvents();
3273}
3274
3275/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003276 * On the display, have a single window, and also an area where there's no window.
3277 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3278 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3279 */
3280TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3282 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003283 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003284
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003285 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003286
3287 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003288 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003289
3290 mDispatcher->waitForIdle();
3291 window->assertNoEvents();
3292
3293 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003294 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003295 mDispatcher->waitForIdle();
3296 window->consumeMotionDown();
3297}
3298
3299/**
3300 * Same test as above, but instead of touching the empty space, the first touch goes to
3301 * non-touchable window.
3302 */
3303TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3305 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003306 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003307 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3308 window1->setTouchable(false);
3309 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003310 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003311 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3312
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003313 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003314
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003315 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003316 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003317
3318 mDispatcher->waitForIdle();
3319 window1->assertNoEvents();
3320 window2->assertNoEvents();
3321
3322 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003323 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003324 mDispatcher->waitForIdle();
3325 window2->consumeMotionDown();
3326}
3327
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003328/**
3329 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3330 * to the event time of the first ACTION_DOWN sent to the particular window.
3331 */
3332TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3334 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003335 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003336 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3337 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003338 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003339 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3340
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003341 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003342
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003343 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003344 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003345
3346 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347
3348 MotionEvent* motionEvent1 = window1->consumeMotion();
3349 ASSERT_NE(motionEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003350 window2->assertNoEvents();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3352 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003353
3354 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003355 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003356 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 MotionEvent* motionEvent2 = window2->consumeMotion();
3358 ASSERT_NE(motionEvent2, nullptr);
3359 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003360 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003361 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003362
3363 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003364 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003365 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003366 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003367
3368 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003369 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003370 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003371 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003372
3373 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3374 window1->consumeMotionMove();
3375 window1->assertNoEvents();
3376
3377 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003378 mDispatcher->notifyMotion(
3379 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003380 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003381 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003382
Prabir Pradhan678438e2023-04-13 19:32:51 +00003383 mDispatcher->notifyMotion(
3384 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003385 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003386 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003387}
3388
Garfield Tandf26e862020-07-01 20:18:19 -07003389TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003390 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003391 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003392 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003393 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003394 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003395 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003396 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003397
3398 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3399
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003400 mDispatcher->onWindowInfosChanged(
3401 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003402
3403 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003405 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003406 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3407 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003408 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003409 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003410 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003411
3412 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003414 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003415 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3416 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003417 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003418 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003419 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3420 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003421
3422 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003424 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003425 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3426 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003427 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003428 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003429 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3430 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003431
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003433 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003434 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3435 AINPUT_SOURCE_MOUSE)
3436 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3437 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003438 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003439 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003440 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003441
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003443 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003444 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3445 AINPUT_SOURCE_MOUSE)
3446 .buttonState(0)
3447 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003449 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003450 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003451
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003453 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003454 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3455 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003456 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003457 .build()));
3458 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3459
3460 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003462 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003463 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3464 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003465 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003466 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003467 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003468
3469 // No more events
3470 windowLeft->assertNoEvents();
3471 windowRight->assertNoEvents();
3472}
3473
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003474/**
3475 * Put two fingers down (and don't release them) and click the mouse button.
3476 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3477 * currently active gesture should be canceled, and the new one should proceed.
3478 */
3479TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3480 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3481 sp<FakeWindowHandle> window =
3482 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3483 window->setFrame(Rect(0, 0, 600, 800));
3484
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003485 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003486
3487 const int32_t touchDeviceId = 4;
3488 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003489
3490 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3492 .deviceId(touchDeviceId)
3493 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3494 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003495
Prabir Pradhan678438e2023-04-13 19:32:51 +00003496 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3497 .deviceId(touchDeviceId)
3498 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3499 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3500 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003501 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3502 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3503
3504 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3506 .deviceId(mouseDeviceId)
3507 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3508 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3509 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003510 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3511 WithPointerCount(2u)));
3512 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3513
Prabir Pradhan678438e2023-04-13 19:32:51 +00003514 mDispatcher->notifyMotion(
3515 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3516 .deviceId(mouseDeviceId)
3517 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3518 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3519 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3522
3523 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3524 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3526 .deviceId(touchDeviceId)
3527 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3528 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3529 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003530 window->assertNoEvents();
3531}
3532
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003533TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3534 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3535
3536 sp<FakeWindowHandle> spyWindow =
3537 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3538 spyWindow->setFrame(Rect(0, 0, 600, 800));
3539 spyWindow->setTrustedOverlay(true);
3540 spyWindow->setSpy(true);
3541 sp<FakeWindowHandle> window =
3542 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3543 window->setFrame(Rect(0, 0, 600, 800));
3544
3545 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003546 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003547
3548 // Send mouse cursor to the window
3549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003550 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003551 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3552 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003553 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003554 .build()));
3555
3556 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3557 WithSource(AINPUT_SOURCE_MOUSE)));
3558 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3559 WithSource(AINPUT_SOURCE_MOUSE)));
3560
3561 window->assertNoEvents();
3562 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003563}
3564
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003565TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3567
3568 sp<FakeWindowHandle> spyWindow =
3569 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3570 spyWindow->setFrame(Rect(0, 0, 600, 800));
3571 spyWindow->setTrustedOverlay(true);
3572 spyWindow->setSpy(true);
3573 sp<FakeWindowHandle> window =
3574 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3575 window->setFrame(Rect(0, 0, 600, 800));
3576
3577 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003578 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003579
3580 // Send mouse cursor to the window
3581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003582 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003583 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3584 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003585 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003586 .build()));
3587
3588 // Move mouse cursor
3589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003590 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003591 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3592 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003593 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003594 .build()));
3595
3596 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3597 WithSource(AINPUT_SOURCE_MOUSE)));
3598 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3599 WithSource(AINPUT_SOURCE_MOUSE)));
3600 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3601 WithSource(AINPUT_SOURCE_MOUSE)));
3602 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3603 WithSource(AINPUT_SOURCE_MOUSE)));
3604 // Touch down on the window
3605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003606 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003607 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3608 AINPUT_SOURCE_TOUCHSCREEN)
3609 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003610 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003611 .build()));
3612 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3613 WithSource(AINPUT_SOURCE_MOUSE)));
3614 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3615 WithSource(AINPUT_SOURCE_MOUSE)));
3616 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3617 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3618 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3619 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3620
3621 // pilfer the motion, retaining the gesture on the spy window.
3622 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3623 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3624 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3625
3626 // Touch UP on the window
3627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003628 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003629 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3630 AINPUT_SOURCE_TOUCHSCREEN)
3631 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003632 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003633 .build()));
3634 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3635 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3636
3637 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3638 // to send a new gesture. It should again go to both windows (spy and the window below), just
3639 // like the first gesture did, before pilfering. The window configuration has not changed.
3640
3641 // One more tap - DOWN
3642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003643 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003644 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3645 AINPUT_SOURCE_TOUCHSCREEN)
3646 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003647 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003648 .build()));
3649 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3650 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3651 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3652 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3653
3654 // Touch UP on the window
3655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003656 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003657 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3658 AINPUT_SOURCE_TOUCHSCREEN)
3659 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003660 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003661 .build()));
3662 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3663 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3664 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3665 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3666
3667 window->assertNoEvents();
3668 spyWindow->assertNoEvents();
3669}
3670
Garfield Tandf26e862020-07-01 20:18:19 -07003671// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3672// directly in this test.
3673TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003675 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003676 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003677 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003678
3679 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3680
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003681 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003682
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003684 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003685 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3686 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003687 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003688 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003689 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003690 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003692 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003693 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3694 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003695 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003696 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003697 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3698 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003699
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003701 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003702 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3703 AINPUT_SOURCE_MOUSE)
3704 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3705 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003706 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003707 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003708 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003709
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003711 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003712 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3713 AINPUT_SOURCE_MOUSE)
3714 .buttonState(0)
3715 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003716 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003717 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003718 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003719
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003721 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003722 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3723 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003724 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003725 .build()));
3726 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3727
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003728 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3729 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3730 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003731 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003732 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3733 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003734 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003735 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003736 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003737}
3738
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003739/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003740 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3741 * is generated.
3742 */
3743TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3745 sp<FakeWindowHandle> window =
3746 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3747 window->setFrame(Rect(0, 0, 1200, 800));
3748
3749 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3750
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003751 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003752
3753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003754 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003755 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3756 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003757 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003758 .build()));
3759 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3760
3761 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003762 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003763 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3764}
3765
3766/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003767 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3768 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003769TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
3770 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
3771 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07003772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3773 sp<FakeWindowHandle> window =
3774 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3775 window->setFrame(Rect(0, 0, 1200, 800));
3776
3777 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3778
3779 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3780
3781 MotionEventBuilder hoverEnterBuilder =
3782 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3784 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3786 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3788 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3789 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3790 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3791}
3792
3793/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003794 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3795 */
3796TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3798 sp<FakeWindowHandle> window =
3799 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3800 window->setFrame(Rect(0, 0, 100, 100));
3801
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003802 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003803
3804 const int32_t mouseDeviceId = 7;
3805 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003806
3807 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3809 .deviceId(mouseDeviceId)
3810 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3811 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003812 window->consumeMotionEvent(
3813 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3814
3815 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3817 .deviceId(touchDeviceId)
3818 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3819 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003820
3821 window->consumeMotionEvent(
3822 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3823 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3824}
3825
3826/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003827 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003828 * The tap causes a HOVER_EXIT event to be generated because the current event
3829 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003830 */
3831TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3832 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3833 sp<FakeWindowHandle> window =
3834 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3835 window->setFrame(Rect(0, 0, 100, 100));
3836
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003837 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3839 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3840 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003841 ASSERT_NO_FATAL_FAILURE(
3842 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3843 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003844
3845 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3847 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3848 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003849 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003850 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3851 WithSource(AINPUT_SOURCE_MOUSE))));
3852
3853 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003854 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3855 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3856
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3858 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3859 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003860 ASSERT_NO_FATAL_FAILURE(
3861 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3862 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3863}
3864
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003865TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3866 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3867 sp<FakeWindowHandle> windowDefaultDisplay =
3868 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3869 ADISPLAY_ID_DEFAULT);
3870 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3871 sp<FakeWindowHandle> windowSecondDisplay =
3872 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3873 SECOND_DISPLAY_ID);
3874 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3875
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003876 mDispatcher->onWindowInfosChanged(
3877 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003878
3879 // Set cursor position in window in default display and check that hover enter and move
3880 // events are generated.
3881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003882 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003883 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3884 AINPUT_SOURCE_MOUSE)
3885 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003886 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003887 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003888 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003889
3890 // Remove all windows in secondary display and check that no event happens on window in
3891 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003892 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3893
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003894 windowDefaultDisplay->assertNoEvents();
3895
3896 // Move cursor position in window in default display and check that only hover move
3897 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003898 mDispatcher->onWindowInfosChanged(
3899 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003901 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003902 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3903 AINPUT_SOURCE_MOUSE)
3904 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003906 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003907 windowDefaultDisplay->consumeMotionEvent(
3908 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3909 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003910 windowDefaultDisplay->assertNoEvents();
3911}
3912
Garfield Tan00f511d2019-06-12 16:55:40 -07003913TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003915
3916 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003917 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003918 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003919 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003920 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003921 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003922
3923 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3924
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003925 mDispatcher->onWindowInfosChanged(
3926 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003927
3928 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3929 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003931 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003932 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003933 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003934 windowRight->assertNoEvents();
3935}
3936
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003937TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003939 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3940 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003941 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003942
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003943 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003944 setFocusedWindow(window);
3945
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003946 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003947
Prabir Pradhan678438e2023-04-13 19:32:51 +00003948 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003949
3950 // Window should receive key down event.
3951 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3952
3953 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3954 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003955 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003956 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003957 AKEY_EVENT_FLAG_CANCELED);
3958}
3959
3960TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003962 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3963 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003964
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003965 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003966
Prabir Pradhan678438e2023-04-13 19:32:51 +00003967 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3968 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003969
3970 // Window should receive motion down event.
3971 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3972
3973 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3974 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003975 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003976 window->consumeMotionEvent(
3977 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003978}
3979
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003980TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3982 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3983 "Fake Window", ADISPLAY_ID_DEFAULT);
3984
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003985 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003986
3987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3988 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3989 .build());
3990
3991 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3992
3993 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3994 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3995 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3996
3997 // After the device has been reset, a new hovering stream can be sent to the window
3998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3999 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4000 .build());
4001 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4002}
4003
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004004TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4005 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004006 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4007 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004008 window->setFocusable(true);
4009
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004010 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004011 setFocusedWindow(window);
4012
4013 window->consumeFocusEvent(true);
4014
Prabir Pradhan678438e2023-04-13 19:32:51 +00004015 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004016 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4017 const nsecs_t injectTime = keyArgs.eventTime;
4018 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004019 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004020 // The dispatching time should be always greater than or equal to intercept key timeout.
4021 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4022 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4023 std::chrono::nanoseconds(interceptKeyTimeout).count());
4024}
4025
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004026/**
4027 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4028 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004029TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004031 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4032 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004033 window->setFocusable(true);
4034
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004035 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004036 setFocusedWindow(window);
4037
4038 window->consumeFocusEvent(true);
4039
Prabir Pradhan678438e2023-04-13 19:32:51 +00004040 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004041 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004042
4043 // Set a value that's significantly larger than the default consumption timeout. If the
4044 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4045 mFakePolicy->setInterceptKeyTimeout(600ms);
4046 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4047 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004048 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4049}
4050
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004051/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004052 * Two windows. First is a regular window. Second does not overlap with the first, and has
4053 * WATCH_OUTSIDE_TOUCH.
4054 * Both windows are owned by the same UID.
4055 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4056 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4057 */
4058TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4059 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004060 sp<FakeWindowHandle> window =
4061 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004062 window->setFrame(Rect{0, 0, 100, 100});
4063
4064 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004065 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004066 ADISPLAY_ID_DEFAULT);
4067 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4068 outsideWindow->setWatchOutsideTouch(true);
4069 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004070 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004071
4072 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004073 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4074 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4075 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004076 window->consumeMotionDown();
4077 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4078 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4079 outsideWindow->consumeMotionEvent(
4080 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
4081}
4082
4083/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004084 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4085 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4086 * ACTION_OUTSIDE event is sent per gesture.
4087 */
4088TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4089 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004091 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4092 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004093 window->setWatchOutsideTouch(true);
4094 window->setFrame(Rect{0, 0, 100, 100});
4095 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004096 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4097 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004098 secondWindow->setFrame(Rect{100, 100, 200, 200});
4099 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004100 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4101 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004102 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004103 mDispatcher->onWindowInfosChanged(
4104 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004105
4106 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004107 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4108 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4109 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004110 window->assertNoEvents();
4111 secondWindow->assertNoEvents();
4112
4113 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4114 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004115 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4116 ADISPLAY_ID_DEFAULT,
4117 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004118 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4119 window->consumeMotionEvent(
4120 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004121 secondWindow->consumeMotionDown();
4122 thirdWindow->assertNoEvents();
4123
4124 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4125 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004126 mDispatcher->notifyMotion(
4127 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4128 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004129 window->assertNoEvents();
4130 secondWindow->consumeMotionMove();
4131 thirdWindow->consumeMotionDown();
4132}
4133
Prabir Pradhan814fe082022-07-22 20:22:18 +00004134TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4135 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004136 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4137 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004138 window->setFocusable(true);
4139
Patrick Williamsd828f302023-04-28 17:52:08 -05004140 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004141 setFocusedWindow(window);
4142
4143 window->consumeFocusEvent(true);
4144
Prabir Pradhan678438e2023-04-13 19:32:51 +00004145 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4146 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4147 mDispatcher->notifyKey(keyDown);
4148 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004149
4150 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4151 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4152
4153 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004154 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004155
4156 window->consumeFocusEvent(false);
4157
Prabir Pradhan678438e2023-04-13 19:32:51 +00004158 mDispatcher->notifyKey(keyDown);
4159 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004160 window->assertNoEvents();
4161}
4162
Arthur Hung96483742022-11-15 03:30:48 +00004163TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4165 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4166 "Fake Window", ADISPLAY_ID_DEFAULT);
4167 // Ensure window is non-split and have some transform.
4168 window->setPreventSplitting(true);
4169 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004171
4172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004173 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004174 {50, 50}))
4175 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4176 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4177
4178 const MotionEvent secondFingerDownEvent =
4179 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4180 .displayId(ADISPLAY_ID_DEFAULT)
4181 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004182 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4183 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004184 .build();
4185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004186 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004187 InputEventInjectionSync::WAIT_FOR_RESULT))
4188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4189
4190 const MotionEvent* event = window->consumeMotion();
4191 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4192 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4193 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4194 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4195 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4196}
4197
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004198/**
4199 * Two windows: a splittable and a non-splittable.
4200 * The non-splittable window shouldn't receive any "incomplete" gestures.
4201 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4202 * The second pointer should be dropped because the initial window is splittable, so it won't get
4203 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4204 * "incomplete" gestures.
4205 */
4206TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4208 sp<FakeWindowHandle> leftWindow =
4209 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4210 ADISPLAY_ID_DEFAULT);
4211 leftWindow->setPreventSplitting(false);
4212 leftWindow->setFrame(Rect(0, 0, 100, 100));
4213 sp<FakeWindowHandle> rightWindow =
4214 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4215 ADISPLAY_ID_DEFAULT);
4216 rightWindow->setPreventSplitting(true);
4217 rightWindow->setFrame(Rect(100, 100, 200, 200));
4218 mDispatcher->onWindowInfosChanged(
4219 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4220
4221 // Touch down on left, splittable window
4222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4223 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4224 .build());
4225 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4226
4227 mDispatcher->notifyMotion(
4228 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4229 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4230 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4231 .build());
4232 leftWindow->assertNoEvents();
4233 rightWindow->assertNoEvents();
4234}
4235
Harry Cuttsb166c002023-05-09 13:06:05 +00004236TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4237 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4238 sp<FakeWindowHandle> window =
4239 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4240 window->setFrame(Rect(0, 0, 400, 400));
4241 sp<FakeWindowHandle> trustedOverlay =
4242 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4243 ADISPLAY_ID_DEFAULT);
4244 trustedOverlay->setSpy(true);
4245 trustedOverlay->setTrustedOverlay(true);
4246
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004247 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004248
4249 // Start a three-finger touchpad swipe
4250 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4251 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4252 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4253 .build());
4254 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4255 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4256 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4257 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4258 .build());
4259 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4260 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4261 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4262 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4263 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4264 .build());
4265
4266 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4267 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4268 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4269
4270 // Move the swipe a bit
4271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4273 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4274 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4275 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4276 .build());
4277
4278 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4279
4280 // End the swipe
4281 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4282 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4283 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4284 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4285 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4286 .build());
4287 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4288 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4289 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4290 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4291 .build());
4292 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4293 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4294 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4295 .build());
4296
4297 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4298 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4299 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4300
4301 window->assertNoEvents();
4302}
4303
4304TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4305 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4306 sp<FakeWindowHandle> window =
4307 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4308 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004309 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004310
4311 // Start a three-finger touchpad swipe
4312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4313 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4314 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4315 .build());
4316 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4317 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4318 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4319 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4320 .build());
4321 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4322 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4323 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4324 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4325 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4326 .build());
4327
4328 // Move the swipe a bit
4329 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4330 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4331 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4332 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4333 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4334 .build());
4335
4336 // End the swipe
4337 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4338 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4339 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4340 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4341 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4342 .build());
4343 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4344 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4345 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4346 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4347 .build());
4348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4349 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4350 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4351 .build());
4352
4353 window->assertNoEvents();
4354}
4355
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004356/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004357 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4358 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004359 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004360 */
4361TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4362 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4363 sp<FakeWindowHandle> window =
4364 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4365 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004366 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004367
4368 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4369 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4370 .downTime(baseTime + 10)
4371 .eventTime(baseTime + 10)
4372 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4373 .build());
4374
4375 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4376
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004377 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004378 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004379
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004381
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004382 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4383 .downTime(baseTime + 10)
4384 .eventTime(baseTime + 30)
4385 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4386 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4387 .build());
4388
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004389 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4390
4391 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004392 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4393 .downTime(baseTime + 10)
4394 .eventTime(baseTime + 40)
4395 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4396 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4397 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004398
4399 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4400
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004401 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4402 .downTime(baseTime + 10)
4403 .eventTime(baseTime + 50)
4404 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4405 .build());
4406
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004407 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4408
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4410 .downTime(baseTime + 60)
4411 .eventTime(baseTime + 60)
4412 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4413 .build());
4414
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004415 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004416}
4417
4418/**
Hu Guo771a7692023-09-17 20:51:08 +08004419 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4420 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4421 * its coordinates should be converted by the transform of the windows of target screen.
4422 */
4423TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4424 // This case will create a window and a spy window on the default display and mirror
4425 // window on the second display. cancel event is sent through spy window pilferPointers
4426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4427
4428 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4429 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4430 spyWindowDefaultDisplay->setTrustedOverlay(true);
4431 spyWindowDefaultDisplay->setSpy(true);
4432
4433 sp<FakeWindowHandle> windowDefaultDisplay =
4434 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4435 ADISPLAY_ID_DEFAULT);
4436 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4437
4438 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4439 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4440
4441 // Add the windows to the dispatcher
4442 mDispatcher->onWindowInfosChanged(
4443 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4444 *windowSecondDisplay->getInfo()},
4445 {},
4446 0,
4447 0});
4448
4449 // Send down to ADISPLAY_ID_DEFAULT
4450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4451 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4452 {100, 100}))
4453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4454
4455 spyWindowDefaultDisplay->consumeMotionDown();
4456 windowDefaultDisplay->consumeMotionDown();
4457
4458 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4459
4460 // windowDefaultDisplay gets cancel
4461 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4462 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4463
4464 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4465 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4466 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4467 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4468 EXPECT_EQ(100, event->getX(0));
4469 EXPECT_EQ(100, event->getY(0));
4470}
4471
4472/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004473 * Ensure the correct coordinate spaces are used by InputDispatcher.
4474 *
4475 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4476 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4477 * space.
4478 */
4479class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4480public:
4481 void SetUp() override {
4482 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004483 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004484 }
4485
4486 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4487 gui::DisplayInfo info;
4488 info.displayId = displayId;
4489 info.transform = transform;
4490 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004491 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004492 }
4493
4494 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4495 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004496 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004497 }
4498
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004499 void removeAllWindowsAndDisplays() {
4500 mDisplayInfos.clear();
4501 mWindowInfos.clear();
4502 }
4503
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004504 // Set up a test scenario where the display has a scaled projection and there are two windows
4505 // on the display.
4506 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4507 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4508 // respectively.
4509 ui::Transform displayTransform;
4510 displayTransform.set(2, 0, 0, 4);
4511 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4512
4513 std::shared_ptr<FakeApplicationHandle> application =
4514 std::make_shared<FakeApplicationHandle>();
4515
4516 // Add two windows to the display. Their frames are represented in the display space.
4517 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004518 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4519 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004520 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4521 addWindow(firstWindow);
4522
4523 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004524 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4525 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004526 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4527 addWindow(secondWindow);
4528 return {std::move(firstWindow), std::move(secondWindow)};
4529 }
4530
4531private:
4532 std::vector<gui::DisplayInfo> mDisplayInfos;
4533 std::vector<gui::WindowInfo> mWindowInfos;
4534};
4535
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004536TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004537 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4538 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004539 // selected so that if the hit test was performed with the point and the bounds being in
4540 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004541 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4542 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4543 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004544
4545 firstWindow->consumeMotionDown();
4546 secondWindow->assertNoEvents();
4547}
4548
4549// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4550// the event should be treated as being in the logical display space.
4551TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4552 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4553 // Send down to the first window. The point is represented in the logical display space. The
4554 // point is selected so that if the hit test was done in logical display space, then it would
4555 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004556 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004557 PointF{75 * 2, 55 * 4});
4558
4559 firstWindow->consumeMotionDown();
4560 secondWindow->assertNoEvents();
4561}
4562
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004563// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4564// event should be treated as being in the logical display space.
4565TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4566 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4567
4568 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4569 ui::Transform injectedEventTransform;
4570 injectedEventTransform.set(matrix);
4571 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4572 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4573
4574 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4575 .displayId(ADISPLAY_ID_DEFAULT)
4576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004578 .x(untransformedPoint.x)
4579 .y(untransformedPoint.y))
4580 .build();
4581 event.transform(matrix);
4582
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004583 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004584 InputEventInjectionSync::WAIT_FOR_RESULT);
4585
4586 firstWindow->consumeMotionDown();
4587 secondWindow->assertNoEvents();
4588}
4589
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004590TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4591 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4592
4593 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004594 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4595 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4596 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004597
4598 firstWindow->assertNoEvents();
4599 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004600 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004601 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4602
4603 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4604 EXPECT_EQ(300, event->getRawX(0));
4605 EXPECT_EQ(880, event->getRawY(0));
4606
4607 // Ensure that the x and y values are in the window's coordinate space.
4608 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4609 // the logical display space. This will be the origin of the window space.
4610 EXPECT_EQ(100, event->getX(0));
4611 EXPECT_EQ(80, event->getY(0));
4612}
4613
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004614/** Ensure consistent behavior of InputDispatcher in all orientations. */
4615class InputDispatcherDisplayOrientationFixture
4616 : public InputDispatcherDisplayProjectionTest,
4617 public ::testing::WithParamInterface<ui::Rotation> {};
4618
4619// This test verifies the touchable region of a window for all rotations of the display by tapping
4620// in different locations on the display, specifically points close to the four corners of a
4621// window.
4622TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4623 constexpr static int32_t displayWidth = 400;
4624 constexpr static int32_t displayHeight = 800;
4625
4626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4627
4628 const auto rotation = GetParam();
4629
4630 // Set up the display with the specified rotation.
4631 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4632 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4633 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4634 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4635 logicalDisplayWidth, logicalDisplayHeight);
4636 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4637
4638 // Create a window with its bounds determined in the logical display.
4639 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4640 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4641 sp<FakeWindowHandle> window =
4642 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4643 window->setFrame(frameInDisplay, displayTransform);
4644 addWindow(window);
4645
4646 // The following points in logical display space should be inside the window.
4647 static const std::array<vec2, 4> insidePoints{
4648 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4649 for (const auto pointInsideWindow : insidePoints) {
4650 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4651 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004652 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4653 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4654 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004655 window->consumeMotionDown();
4656
Prabir Pradhan678438e2023-04-13 19:32:51 +00004657 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4658 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4659 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004660 window->consumeMotionUp();
4661 }
4662
4663 // The following points in logical display space should be outside the window.
4664 static const std::array<vec2, 5> outsidePoints{
4665 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4666 for (const auto pointOutsideWindow : outsidePoints) {
4667 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4668 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004669 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4670 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4671 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004672
Prabir Pradhan678438e2023-04-13 19:32:51 +00004673 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4674 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4675 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004676 }
4677 window->assertNoEvents();
4678}
4679
4680// Run the precision tests for all rotations.
4681INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4682 InputDispatcherDisplayOrientationFixture,
4683 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4684 ui::ROTATION_270),
4685 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4686 return ftl::enum_string(testParamInfo.param);
4687 });
4688
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004689using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4690 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004691
4692class TransferTouchFixture : public InputDispatcherTest,
4693 public ::testing::WithParamInterface<TransferFunction> {};
4694
4695TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004697
4698 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004699 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004700 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4701 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004702 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004703 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004704 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4705 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004706 sp<FakeWindowHandle> wallpaper =
4707 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4708 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004709 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004710 mDispatcher->onWindowInfosChanged(
4711 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004712
4713 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004714 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4715 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004716
Svet Ganov5d3bc372020-01-26 23:11:07 -08004717 // Only the first window should get the down event
4718 firstWindow->consumeMotionDown();
4719 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004720 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004721
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004722 // Transfer touch to the second window
4723 TransferFunction f = GetParam();
4724 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4725 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004726 // The first window gets cancel and the second gets down
4727 firstWindow->consumeMotionCancel();
4728 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004729 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004730
4731 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004732 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4733 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004734 // The first window gets no events and the second gets up
4735 firstWindow->assertNoEvents();
4736 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004737 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004738}
4739
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004740/**
4741 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4742 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4743 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4744 * natural to the user.
4745 * In this test, we are sending a pointer to both spy window and first window. We then try to
4746 * transfer touch to the second window. The dispatcher should identify the first window as the
4747 * one that should lose the gesture, and therefore the action should be to move the gesture from
4748 * the first window to the second.
4749 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4750 * the other API, as well.
4751 */
4752TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4754
4755 // Create a couple of windows + a spy window
4756 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004757 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004758 spyWindow->setTrustedOverlay(true);
4759 spyWindow->setSpy(true);
4760 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004761 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004762 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004763 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004764
4765 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004766 mDispatcher->onWindowInfosChanged(
4767 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004768
4769 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004770 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4771 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004772 // Only the first window and spy should get the down event
4773 spyWindow->consumeMotionDown();
4774 firstWindow->consumeMotionDown();
4775
4776 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4777 // if f === 'transferTouch'.
4778 TransferFunction f = GetParam();
4779 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4780 ASSERT_TRUE(success);
4781 // The first window gets cancel and the second gets down
4782 firstWindow->consumeMotionCancel();
4783 secondWindow->consumeMotionDown();
4784
4785 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004786 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4787 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004788 // The first window gets no events and the second+spy get up
4789 firstWindow->assertNoEvents();
4790 spyWindow->consumeMotionUp();
4791 secondWindow->consumeMotionUp();
4792}
4793
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004794TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004796
4797 PointF touchPoint = {10, 10};
4798
4799 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004800 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004801 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4802 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004803 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004804 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004805 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4806 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004807 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004808
4809 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004810 mDispatcher->onWindowInfosChanged(
4811 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004812
4813 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004814 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4815 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4816 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004817 // Only the first window should get the down event
4818 firstWindow->consumeMotionDown();
4819 secondWindow->assertNoEvents();
4820
4821 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004822 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4823 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004824 // Only the first window should get the pointer down event
4825 firstWindow->consumeMotionPointerDown(1);
4826 secondWindow->assertNoEvents();
4827
4828 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004829 TransferFunction f = GetParam();
4830 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4831 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004832 // The first window gets cancel and the second gets down and pointer down
4833 firstWindow->consumeMotionCancel();
4834 secondWindow->consumeMotionDown();
4835 secondWindow->consumeMotionPointerDown(1);
4836
4837 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004838 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4839 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004840 // The first window gets nothing and the second gets pointer up
4841 firstWindow->assertNoEvents();
4842 secondWindow->consumeMotionPointerUp(1);
4843
4844 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004845 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4846 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004847 // The first window gets nothing and the second gets up
4848 firstWindow->assertNoEvents();
4849 secondWindow->consumeMotionUp();
4850}
4851
Arthur Hungc539dbb2022-12-08 07:45:36 +00004852TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4854
4855 // Create a couple of windows
4856 sp<FakeWindowHandle> firstWindow =
4857 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4858 ADISPLAY_ID_DEFAULT);
4859 firstWindow->setDupTouchToWallpaper(true);
4860 sp<FakeWindowHandle> secondWindow =
4861 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4862 ADISPLAY_ID_DEFAULT);
4863 secondWindow->setDupTouchToWallpaper(true);
4864
4865 sp<FakeWindowHandle> wallpaper1 =
4866 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4867 wallpaper1->setIsWallpaper(true);
4868
4869 sp<FakeWindowHandle> wallpaper2 =
4870 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4871 wallpaper2->setIsWallpaper(true);
4872 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004873 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
4874 *secondWindow->getInfo(), *wallpaper2->getInfo()},
4875 {},
4876 0,
4877 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00004878
4879 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004880 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4881 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004882
4883 // Only the first window should get the down event
4884 firstWindow->consumeMotionDown();
4885 secondWindow->assertNoEvents();
4886 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4887 wallpaper2->assertNoEvents();
4888
4889 // Transfer touch focus to the second window
4890 TransferFunction f = GetParam();
4891 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4892 ASSERT_TRUE(success);
4893
4894 // The first window gets cancel and the second gets down
4895 firstWindow->consumeMotionCancel();
4896 secondWindow->consumeMotionDown();
4897 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4898 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4899
4900 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004901 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4902 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004903 // The first window gets no events and the second gets up
4904 firstWindow->assertNoEvents();
4905 secondWindow->consumeMotionUp();
4906 wallpaper1->assertNoEvents();
4907 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4908}
4909
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004910// For the cases of single pointer touch and two pointers non-split touch, the api's
4911// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4912// for the case where there are multiple pointers split across several windows.
4913INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4914 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004915 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4916 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004917 return dispatcher->transferTouch(destChannelToken,
4918 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004919 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004920 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4921 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004922 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004923 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004924 }));
4925
Svet Ganov5d3bc372020-01-26 23:11:07 -08004926TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004927 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004928
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004929 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004930 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4931 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004932 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004933
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004934 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004935 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4936 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004937 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004938
4939 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004940 mDispatcher->onWindowInfosChanged(
4941 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004942
4943 PointF pointInFirst = {300, 200};
4944 PointF pointInSecond = {300, 600};
4945
4946 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004947 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4948 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4949 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004950 // Only the first window should get the down event
4951 firstWindow->consumeMotionDown();
4952 secondWindow->assertNoEvents();
4953
4954 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004955 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4956 ADISPLAY_ID_DEFAULT,
4957 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004958 // The first window gets a move and the second a down
4959 firstWindow->consumeMotionMove();
4960 secondWindow->consumeMotionDown();
4961
4962 // Transfer touch focus to the second window
4963 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4964 // The first window gets cancel and the new gets pointer down (it already saw down)
4965 firstWindow->consumeMotionCancel();
4966 secondWindow->consumeMotionPointerDown(1);
4967
4968 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004969 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4970 ADISPLAY_ID_DEFAULT,
4971 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004972 // The first window gets nothing and the second gets pointer up
4973 firstWindow->assertNoEvents();
4974 secondWindow->consumeMotionPointerUp(1);
4975
4976 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004977 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4978 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004979 // The first window gets nothing and the second gets up
4980 firstWindow->assertNoEvents();
4981 secondWindow->consumeMotionUp();
4982}
4983
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004984// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4985// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4986// touch is not supported, so the touch should continue on those windows and the transferred-to
4987// window should get nothing.
4988TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4990
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004991 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004992 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4993 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004994 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004995
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004996 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004997 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4998 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004999 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005000
5001 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005002 mDispatcher->onWindowInfosChanged(
5003 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005004
5005 PointF pointInFirst = {300, 200};
5006 PointF pointInSecond = {300, 600};
5007
5008 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005009 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5010 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5011 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005012 // Only the first window should get the down event
5013 firstWindow->consumeMotionDown();
5014 secondWindow->assertNoEvents();
5015
5016 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005017 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5018 ADISPLAY_ID_DEFAULT,
5019 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005020 // The first window gets a move and the second a down
5021 firstWindow->consumeMotionMove();
5022 secondWindow->consumeMotionDown();
5023
5024 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005025 const bool transferred =
5026 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005027 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5028 ASSERT_FALSE(transferred);
5029 firstWindow->assertNoEvents();
5030 secondWindow->assertNoEvents();
5031
5032 // The rest of the dispatch should proceed as normal
5033 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005034 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5035 ADISPLAY_ID_DEFAULT,
5036 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005037 // The first window gets MOVE and the second gets pointer up
5038 firstWindow->consumeMotionMove();
5039 secondWindow->consumeMotionUp();
5040
5041 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005042 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5043 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005044 // The first window gets nothing and the second gets up
5045 firstWindow->consumeMotionUp();
5046 secondWindow->assertNoEvents();
5047}
5048
Arthur Hungabbb9d82021-09-01 14:52:30 +00005049// This case will create two windows and one mirrored window on the default display and mirror
5050// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5051// the windows info of second display before default display.
5052TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5054 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005055 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005056 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005057 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005058 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005059 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005060
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005061 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005062 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005063
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005064 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005065 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005066
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005067 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005068 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005069
5070 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005071 mDispatcher->onWindowInfosChanged(
5072 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5073 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5074 *secondWindowInPrimary->getInfo()},
5075 {},
5076 0,
5077 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005078
5079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005080 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005081 {50, 50}))
5082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5083
5084 // Window should receive motion event.
5085 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5086
5087 // Transfer touch focus
5088 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5089 secondWindowInPrimary->getToken()));
5090 // The first window gets cancel.
5091 firstWindowInPrimary->consumeMotionCancel();
5092 secondWindowInPrimary->consumeMotionDown();
5093
5094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005095 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005096 ADISPLAY_ID_DEFAULT, {150, 50}))
5097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5098 firstWindowInPrimary->assertNoEvents();
5099 secondWindowInPrimary->consumeMotionMove();
5100
5101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005102 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005103 {150, 50}))
5104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5105 firstWindowInPrimary->assertNoEvents();
5106 secondWindowInPrimary->consumeMotionUp();
5107}
5108
5109// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5110// 'transferTouch' api.
5111TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5113 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005114 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005115 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005116 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005117 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005118 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005119
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005120 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005121 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005122
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005123 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005124 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005125
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005126 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005127 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005128
5129 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005130 mDispatcher->onWindowInfosChanged(
5131 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5132 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5133 *secondWindowInPrimary->getInfo()},
5134 {},
5135 0,
5136 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005137
5138 // Touch on second display.
5139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005140 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5141 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005142 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5143
5144 // Window should receive motion event.
5145 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5146
5147 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005148 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005149
5150 // The first window gets cancel.
5151 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5152 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5153
5154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005155 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005156 SECOND_DISPLAY_ID, {150, 50}))
5157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5158 firstWindowInPrimary->assertNoEvents();
5159 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5160
5161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005162 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005163 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5164 firstWindowInPrimary->assertNoEvents();
5165 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5166}
5167
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005168TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005170 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5171 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005172
Vishnu Nair47074b82020-08-14 11:54:47 -07005173 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005174 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005175 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005176
5177 window->consumeFocusEvent(true);
5178
Prabir Pradhan678438e2023-04-13 19:32:51 +00005179 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005180
5181 // Window should receive key down event.
5182 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005183
5184 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005185 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005186 mFakePolicy->assertUserActivityPoked();
5187}
5188
5189TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5191 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5192 "Fake Window", ADISPLAY_ID_DEFAULT);
5193
5194 window->setDisableUserActivity(true);
5195 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005196 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005197 setFocusedWindow(window);
5198
5199 window->consumeFocusEvent(true);
5200
5201 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5202
5203 // Window should receive key down event.
5204 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5205
5206 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005207 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005208 mFakePolicy->assertUserActivityNotPoked();
5209}
5210
5211TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5213 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5214 "Fake Window", ADISPLAY_ID_DEFAULT);
5215
5216 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005217 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005218 setFocusedWindow(window);
5219
5220 window->consumeFocusEvent(true);
5221
5222 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5223 mDispatcher->waitForIdle();
5224
5225 // System key is not passed down
5226 window->assertNoEvents();
5227
5228 // Should have poked user activity
5229 mFakePolicy->assertUserActivityPoked();
5230}
5231
5232TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5234 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5235 "Fake Window", ADISPLAY_ID_DEFAULT);
5236
5237 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005238 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005239 setFocusedWindow(window);
5240
5241 window->consumeFocusEvent(true);
5242
5243 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5244 mDispatcher->waitForIdle();
5245
5246 // System key is not passed down
5247 window->assertNoEvents();
5248
5249 // Should have poked user activity
5250 mFakePolicy->assertUserActivityPoked();
5251}
5252
5253TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5254 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5255 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5256 "Fake Window", ADISPLAY_ID_DEFAULT);
5257
5258 window->setDisableUserActivity(true);
5259 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005260 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005261 setFocusedWindow(window);
5262
5263 window->consumeFocusEvent(true);
5264
5265 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5266 mDispatcher->waitForIdle();
5267
5268 // System key is not passed down
5269 window->assertNoEvents();
5270
5271 // Should have poked user activity
5272 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005273}
5274
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005275TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5277 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5278 "Fake Window", ADISPLAY_ID_DEFAULT);
5279
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005280 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005281
5282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005283 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005284 ADISPLAY_ID_DEFAULT, {100, 100}))
5285 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5286
5287 window->consumeMotionEvent(
5288 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5289
5290 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005291 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005292 mFakePolicy->assertUserActivityPoked();
5293}
5294
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005295TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005296 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005297 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5298 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005299
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005300 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005301
Prabir Pradhan678438e2023-04-13 19:32:51 +00005302 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005303 mDispatcher->waitForIdle();
5304
5305 window->assertNoEvents();
5306}
5307
5308// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5309TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005311 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5312 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005313
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005314 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005315
5316 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005317 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005318 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005319 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5320 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005321
5322 // Window should receive only the motion event
5323 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5324 window->assertNoEvents(); // Key event or focus event will not be received
5325}
5326
arthurhungea3f4fc2020-12-21 23:18:53 +08005327TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5329
arthurhungea3f4fc2020-12-21 23:18:53 +08005330 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005331 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5332 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005333 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005334
arthurhungea3f4fc2020-12-21 23:18:53 +08005335 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005336 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5337 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005338 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005339
5340 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005341 mDispatcher->onWindowInfosChanged(
5342 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005343
5344 PointF pointInFirst = {300, 200};
5345 PointF pointInSecond = {300, 600};
5346
5347 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005348 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5349 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5350 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005351 // Only the first window should get the down event
5352 firstWindow->consumeMotionDown();
5353 secondWindow->assertNoEvents();
5354
5355 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005356 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5357 ADISPLAY_ID_DEFAULT,
5358 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005359 // The first window gets a move and the second a down
5360 firstWindow->consumeMotionMove();
5361 secondWindow->consumeMotionDown();
5362
5363 // Send pointer cancel to the second window
5364 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005365 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005366 {pointInFirst, pointInSecond});
5367 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005368 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005369 // The first window gets move and the second gets cancel.
5370 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5371 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5372
5373 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005374 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5375 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005376 // The first window gets up and the second gets nothing.
5377 firstWindow->consumeMotionUp();
5378 secondWindow->assertNoEvents();
5379}
5380
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005381TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5383
5384 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005385 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005386 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005387 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5388 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5389 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5390
Harry Cutts33476232023-01-30 19:57:29 +00005391 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005392 window->assertNoEvents();
5393 mDispatcher->waitForIdle();
5394}
5395
chaviwd1c23182019-12-20 18:44:56 -08005396class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00005397public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005398 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005399 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07005400 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08005401 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07005402 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00005403 }
5404
chaviwd1c23182019-12-20 18:44:56 -08005405 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
5406
5407 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005408 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
5409 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08005410 }
5411
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005412 std::optional<int32_t> receiveEvent() {
5413 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
5414 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005415
5416 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
5417
chaviwd1c23182019-12-20 18:44:56 -08005418 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005419 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08005420 expectedDisplayId, expectedFlags);
5421 }
5422
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005423 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005424 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005425 expectedDisplayId, expectedFlags);
5426 }
5427
chaviwd1c23182019-12-20 18:44:56 -08005428 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005429 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08005430 expectedDisplayId, expectedFlags);
5431 }
5432
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005433 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005434 mInputReceiver->consumeMotionEvent(
5435 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
5436 WithDisplayId(expectedDisplayId),
5437 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005438 }
5439
Arthur Hungfbfa5722021-11-16 02:45:54 +00005440 void consumeMotionPointerDown(int32_t pointerIdx) {
5441 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
5442 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005443 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005444 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00005445 }
5446
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005447 MotionEvent* consumeMotion() { return mInputReceiver->consumeMotion(); }
Evan Rosky84f07f02021-04-16 10:42:42 -07005448
chaviwd1c23182019-12-20 18:44:56 -08005449 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5450
5451private:
5452 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005453};
5454
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005455using InputDispatcherMonitorTest = InputDispatcherTest;
5456
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005457/**
5458 * Two entities that receive touch: A window, and a global monitor.
5459 * The touch goes to the window, and then the window disappears.
5460 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5461 * for the monitor, as well.
5462 * 1. foregroundWindow
5463 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5464 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005465TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5467 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005468 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005469
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005470 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005471
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005472 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005474 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005475 {100, 200}))
5476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5477
5478 // Both the foreground window and the global monitor should receive the touch down
5479 window->consumeMotionDown();
5480 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5481
5482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005483 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005484 ADISPLAY_ID_DEFAULT, {110, 200}))
5485 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5486
5487 window->consumeMotionMove();
5488 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5489
5490 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005491 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005492 window->consumeMotionCancel();
5493 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5494
5495 // If more events come in, there will be no more foreground window to send them to. This will
5496 // cause a cancel for the monitor, as well.
5497 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005498 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005499 ADISPLAY_ID_DEFAULT, {120, 200}))
5500 << "Injection should fail because the window was removed";
5501 window->assertNoEvents();
5502 // Global monitor now gets the cancel
5503 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5504}
5505
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005506TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005507 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005508 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5509 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005511
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005512 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005513
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005515 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005517 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005518 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005519}
5520
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005521TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5522 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005523
Chris Yea209fde2020-07-22 13:54:51 -07005524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005525 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5526 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005528
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005530 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005531 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005532 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005533 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005534
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005535 // Pilfer pointers from the monitor.
5536 // This should not do anything and the window should continue to receive events.
5537 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005538
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005540 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005541 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005543
5544 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5545 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005546}
5547
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005548TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5551 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005552 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005553 window->setWindowOffset(20, 40);
5554 window->setWindowTransform(0, 1, -1, 0);
5555
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005556 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005557
5558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005559 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5561 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5562 MotionEvent* event = monitor.consumeMotion();
5563 // Even though window has transform, gesture monitor must not.
5564 ASSERT_EQ(ui::Transform(), event->getTransform());
5565}
5566
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005567TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005568 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005569 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005570
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005571 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005572 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005573 << "Injection should fail if there is a monitor, but no touchable window";
5574 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005575}
5576
chaviw81e2bb92019-12-18 15:03:51 -08005577TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005579 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5580 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005581
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005582 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08005583
5584 NotifyMotionArgs motionArgs =
5585 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5586 ADISPLAY_ID_DEFAULT);
5587
Prabir Pradhan678438e2023-04-13 19:32:51 +00005588 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005589 // Window should receive motion down event.
5590 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5591
5592 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005593 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005594 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5595 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5596 motionArgs.pointerCoords[0].getX() - 10);
5597
Prabir Pradhan678438e2023-04-13 19:32:51 +00005598 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005599 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005600 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005601}
5602
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005603/**
5604 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5605 * the device default right away. In the test scenario, we check both the default value,
5606 * and the action of enabling / disabling.
5607 */
5608TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005610 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5611 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005612 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005613
5614 // Set focused application.
5615 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005616 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005617
5618 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005619 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005620 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005621 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005622
5623 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005624 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005625 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005626 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005627
5628 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005629 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005630 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005631 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005632 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005633 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005634 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005635 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005636
5637 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005638 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005639 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00005640 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005641
5642 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005643 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005644 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005645 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005646 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005647 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005648 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005649 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005650
5651 window->assertNoEvents();
5652}
5653
Gang Wange9087892020-01-07 12:17:14 -05005654TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005655 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005656 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5657 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005658
5659 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005660 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005661
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005663 setFocusedWindow(window);
5664
Harry Cutts33476232023-01-30 19:57:29 +00005665 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005666
Prabir Pradhan678438e2023-04-13 19:32:51 +00005667 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5668 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005669
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005670 KeyEvent* event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05005671 ASSERT_NE(event, nullptr);
5672
5673 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5674 ASSERT_NE(verified, nullptr);
5675 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5676
5677 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5678 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5679 ASSERT_EQ(keyArgs.source, verified->source);
5680 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5681
5682 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5683
5684 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005685 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005686 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005687 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5688 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5689 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5690 ASSERT_EQ(0, verifiedKey.repeatCount);
5691}
5692
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005693TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005695 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5696 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005697
5698 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5699
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005700 ui::Transform transform;
5701 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5702
5703 gui::DisplayInfo displayInfo;
5704 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5705 displayInfo.transform = transform;
5706
Patrick Williamsd828f302023-04-28 17:52:08 -05005707 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005708
Prabir Pradhan678438e2023-04-13 19:32:51 +00005709 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005710 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5711 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005712 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005713
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005714 MotionEvent* event = window->consumeMotion();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005715 ASSERT_NE(event, nullptr);
5716
5717 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5718 ASSERT_NE(verified, nullptr);
5719 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5720
5721 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5722 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5723 EXPECT_EQ(motionArgs.source, verified->source);
5724 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5725
5726 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5727
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005728 const vec2 rawXY =
5729 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5730 motionArgs.pointerCoords[0].getXYValue());
5731 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5732 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005733 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005734 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005735 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005736 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5737 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5738}
5739
chaviw09c8d2d2020-08-24 15:48:26 -07005740/**
5741 * Ensure that separate calls to sign the same data are generating the same key.
5742 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5743 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5744 * tests.
5745 */
5746TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5747 KeyEvent event = getTestKeyEvent();
5748 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5749
5750 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5751 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5752 ASSERT_EQ(hmac1, hmac2);
5753}
5754
5755/**
5756 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5757 */
5758TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5759 KeyEvent event = getTestKeyEvent();
5760 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5761 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5762
5763 verifiedEvent.deviceId += 1;
5764 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5765
5766 verifiedEvent.source += 1;
5767 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5768
5769 verifiedEvent.eventTimeNanos += 1;
5770 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5771
5772 verifiedEvent.displayId += 1;
5773 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5774
5775 verifiedEvent.action += 1;
5776 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5777
5778 verifiedEvent.downTimeNanos += 1;
5779 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5780
5781 verifiedEvent.flags += 1;
5782 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5783
5784 verifiedEvent.keyCode += 1;
5785 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5786
5787 verifiedEvent.scanCode += 1;
5788 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5789
5790 verifiedEvent.metaState += 1;
5791 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5792
5793 verifiedEvent.repeatCount += 1;
5794 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5795}
5796
Vishnu Nair958da932020-08-21 17:12:37 -07005797TEST_F(InputDispatcherTest, SetFocusedWindow) {
5798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5799 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005800 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005801 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005802 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005803 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5804
5805 // Top window is also focusable but is not granted focus.
5806 windowTop->setFocusable(true);
5807 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005808 mDispatcher->onWindowInfosChanged(
5809 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005810 setFocusedWindow(windowSecond);
5811
5812 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005814 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005815
5816 // Focused window should receive event.
5817 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5818 windowTop->assertNoEvents();
5819}
5820
5821TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5823 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005824 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005825 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5826
5827 window->setFocusable(true);
5828 // Release channel for window is no longer valid.
5829 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005830 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005831 setFocusedWindow(window);
5832
5833 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005834 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005835
5836 // window channel is invalid, so it should not receive any input event.
5837 window->assertNoEvents();
5838}
5839
5840TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5842 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005843 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005844 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005845 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5846
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005848 setFocusedWindow(window);
5849
5850 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005851 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07005852
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005853 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005854 window->assertNoEvents();
5855}
5856
5857TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5859 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005860 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005861 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005862 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005863 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5864
5865 windowTop->setFocusable(true);
5866 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005867 mDispatcher->onWindowInfosChanged(
5868 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005869 setFocusedWindow(windowTop);
5870 windowTop->consumeFocusEvent(true);
5871
Chavi Weingarten847e8512023-03-29 00:26:09 +00005872 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005873 mDispatcher->onWindowInfosChanged(
5874 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005875 windowSecond->consumeFocusEvent(true);
5876 windowTop->consumeFocusEvent(false);
5877
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005879 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005880
5881 // Focused window should receive event.
5882 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5883}
5884
Chavi Weingarten847e8512023-03-29 00:26:09 +00005885TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005886 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5887 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005888 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005889 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005890 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005891 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5892
5893 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005894 windowSecond->setFocusable(false);
5895 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005896 mDispatcher->onWindowInfosChanged(
5897 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005898 setFocusedWindow(windowTop);
5899 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005900
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00005902 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005903
5904 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005905 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005906 windowSecond->assertNoEvents();
5907}
5908
5909TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5910 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5911 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005912 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005913 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005914 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5915 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005916 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5917
5918 window->setFocusable(true);
5919 previousFocusedWindow->setFocusable(true);
5920 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005921 mDispatcher->onWindowInfosChanged(
5922 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005923 setFocusedWindow(previousFocusedWindow);
5924 previousFocusedWindow->consumeFocusEvent(true);
5925
5926 // Requesting focus on invisible window takes focus from currently focused window.
5927 setFocusedWindow(window);
5928 previousFocusedWindow->consumeFocusEvent(false);
5929
5930 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005932 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
5933 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005934
5935 // Window does not get focus event or key down.
5936 window->assertNoEvents();
5937
5938 // Window becomes visible.
5939 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005940 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005941
5942 // Window receives focus event.
5943 window->consumeFocusEvent(true);
5944 // Focused window receives key down.
5945 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5946}
5947
Vishnu Nair599f1412021-06-21 10:39:58 -07005948TEST_F(InputDispatcherTest, DisplayRemoved) {
5949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5950 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005951 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005952 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5953
5954 // window is granted focus.
5955 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005956 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07005957 setFocusedWindow(window);
5958 window->consumeFocusEvent(true);
5959
5960 // When a display is removed window loses focus.
5961 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5962 window->consumeFocusEvent(false);
5963}
5964
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005965/**
5966 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5967 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5968 * of the 'slipperyEnterWindow'.
5969 *
5970 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5971 * a way so that the touched location is no longer covered by the top window.
5972 *
5973 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5974 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5975 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5976 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5977 * with ACTION_DOWN).
5978 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5979 * window moved itself away from the touched location and had Flag::SLIPPERY.
5980 *
5981 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5982 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5983 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5984 *
5985 * In this test, we ensure that the event received by the bottom window has
5986 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5987 */
5988TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005989 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005990 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005991
5992 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5993 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5994
5995 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005996 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005997 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005998 // Make sure this one overlaps the bottom window
5999 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6000 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6001 // one. Windows with the same owner are not considered to be occluding each other.
6002 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6003
6004 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006005 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006006 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6007
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006008 mDispatcher->onWindowInfosChanged(
6009 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006010
6011 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006012 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6013 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6014 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006015 slipperyExitWindow->consumeMotionDown();
6016 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006017 mDispatcher->onWindowInfosChanged(
6018 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006019
Prabir Pradhan678438e2023-04-13 19:32:51 +00006020 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6021 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6022 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006023
6024 slipperyExitWindow->consumeMotionCancel();
6025
6026 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6027 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6028}
6029
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006030/**
6031 * Two windows, one on the left and another on the right. The left window is slippery. The right
6032 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6033 * touch moves from the left window into the right window, the gesture should continue to go to the
6034 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6035 * reproduces a crash.
6036 */
6037TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6039
6040 sp<FakeWindowHandle> leftSlipperyWindow =
6041 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6042 leftSlipperyWindow->setSlippery(true);
6043 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6044
6045 sp<FakeWindowHandle> rightDropTouchesWindow =
6046 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6047 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6048 rightDropTouchesWindow->setDropInput(true);
6049
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006050 mDispatcher->onWindowInfosChanged(
6051 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006052
6053 // Start touch in the left window
6054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6055 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6056 .build());
6057 leftSlipperyWindow->consumeMotionDown();
6058
6059 // And move it into the right window
6060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6061 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6062 .build());
6063
6064 // Since the right window isn't eligible to receive input, touch does not slip.
6065 // The left window continues to receive the gesture.
6066 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6067 rightDropTouchesWindow->assertNoEvents();
6068}
6069
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006070/**
6071 * A single window is on screen first. Touch is injected into that window. Next, a second window
6072 * appears. Since the first window is slippery, touch will move from the first window to the second.
6073 */
6074TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6076 sp<FakeWindowHandle> originalWindow =
6077 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6078 originalWindow->setFrame(Rect(0, 0, 200, 200));
6079 originalWindow->setSlippery(true);
6080
6081 sp<FakeWindowHandle> appearingWindow =
6082 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6083 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6084
6085 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6086
6087 // Touch down on the original window
6088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6089 injectMotionEvent(*mDispatcher,
6090 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6091 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6092 .build()));
6093 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6094
6095 // Now, a new window appears. This could be, for example, a notification shade that appears
6096 // after user starts to drag down on the launcher window.
6097 mDispatcher->onWindowInfosChanged(
6098 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6100 injectMotionEvent(*mDispatcher,
6101 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6102 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6103 .build()));
6104 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6105 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6107 injectMotionEvent(*mDispatcher,
6108 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6109 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6110 .build()));
6111 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6112
6113 originalWindow->assertNoEvents();
6114 appearingWindow->assertNoEvents();
6115}
6116
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006117TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006118 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6120
6121 sp<FakeWindowHandle> leftWindow =
6122 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6123 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006124 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006125
6126 sp<FakeWindowHandle> rightSpy =
6127 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6128 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006129 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006130 rightSpy->setSpy(true);
6131 rightSpy->setTrustedOverlay(true);
6132
6133 sp<FakeWindowHandle> rightWindow =
6134 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6135 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006136 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006137
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006138 mDispatcher->onWindowInfosChanged(
6139 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006140
6141 // Touch in the left window
6142 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6143 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6144 .build());
6145 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6146 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006147 ASSERT_NO_FATAL_FAILURE(
6148 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006149
6150 // Touch another finger over the right windows
6151 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6152 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6153 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6154 .build());
6155 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6156 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6157 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6158 mDispatcher->waitForIdle();
6159 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006160 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6161 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006162
6163 // Release finger over left window. The UP actions are not treated as device interaction.
6164 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6165 // is part of the UP action, we do not treat this as device interaction.
6166 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6167 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6168 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6169 .build());
6170 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6171 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6172 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6173 mDispatcher->waitForIdle();
6174 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6175
6176 // Move remaining finger
6177 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6178 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6179 .build());
6180 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6181 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6182 mDispatcher->waitForIdle();
6183 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006184 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006185
6186 // Release all fingers
6187 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6188 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6189 .build());
6190 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6191 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6192 mDispatcher->waitForIdle();
6193 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6194}
6195
6196TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6198
6199 sp<FakeWindowHandle> window =
6200 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6201 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006202 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006203
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006205 setFocusedWindow(window);
6206 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6207
6208 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6209 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6210 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006211 ASSERT_NO_FATAL_FAILURE(
6212 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006213
6214 // The UP actions are not treated as device interaction.
6215 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6216 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6217 mDispatcher->waitForIdle();
6218 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6219}
6220
Garfield Tan1c7bc862020-01-28 13:24:04 -08006221class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6222protected:
6223 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
6224 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
6225
Chris Yea209fde2020-07-22 13:54:51 -07006226 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006227 sp<FakeWindowHandle> mWindow;
6228
6229 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006230 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006231 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006232 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006233 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006234 ASSERT_EQ(OK, mDispatcher->start());
6235
6236 setUpWindow();
6237 }
6238
6239 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006240 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006241 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006242
Vishnu Nair47074b82020-08-14 11:54:47 -07006243 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006244 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006245 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006246 mWindow->consumeFocusEvent(true);
6247 }
6248
Chris Ye2ad95392020-09-01 13:44:44 -07006249 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006250 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006251 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006252 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006253 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006254
6255 // Window should receive key down event.
6256 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6257 }
6258
6259 void expectKeyRepeatOnce(int32_t repeatCount) {
6260 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006261 mWindow->consumeKeyEvent(
6262 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08006263 }
6264
Chris Ye2ad95392020-09-01 13:44:44 -07006265 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08006266 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07006267 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006268 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00006269 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006270
6271 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006272 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00006273 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006274 }
6275};
6276
6277TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00006278 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006279 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6280 expectKeyRepeatOnce(repeatCount);
6281 }
6282}
6283
6284TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00006285 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006286 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6287 expectKeyRepeatOnce(repeatCount);
6288 }
Harry Cutts33476232023-01-30 19:57:29 +00006289 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006290 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08006291 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
6292 expectKeyRepeatOnce(repeatCount);
6293 }
6294}
6295
6296TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006297 sendAndConsumeKeyDown(/*deviceId=*/1);
6298 expectKeyRepeatOnce(/*repeatCount=*/1);
6299 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006300 mWindow->assertNoEvents();
6301}
6302
6303TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006304 sendAndConsumeKeyDown(/*deviceId=*/1);
6305 expectKeyRepeatOnce(/*repeatCount=*/1);
6306 sendAndConsumeKeyDown(/*deviceId=*/2);
6307 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006308 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00006309 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006310 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00006311 expectKeyRepeatOnce(/*repeatCount=*/2);
6312 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07006313 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00006314 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006315 mWindow->assertNoEvents();
6316}
6317
6318TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00006319 sendAndConsumeKeyDown(/*deviceId=*/1);
6320 expectKeyRepeatOnce(/*repeatCount=*/1);
6321 sendAndConsumeKeyDown(/*deviceId=*/2);
6322 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07006323 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00006324 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07006325 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08006326 mWindow->assertNoEvents();
6327}
6328
liushenxiang42232912021-05-21 20:24:09 +08006329TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
6330 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00006331 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006332 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08006333 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
6334 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
6335 mWindow->assertNoEvents();
6336}
6337
Garfield Tan1c7bc862020-01-28 13:24:04 -08006338TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006339 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006340 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006341 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006342 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006343 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6344 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
6345 IdGenerator::getSource(repeatEvent->getId()));
6346 }
6347}
6348
6349TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00006350 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00006351 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006352
6353 std::unordered_set<int32_t> idSet;
6354 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006355 KeyEvent* repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08006356 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
6357 int32_t id = repeatEvent->getId();
6358 EXPECT_EQ(idSet.end(), idSet.find(id));
6359 idSet.insert(id);
6360 }
6361}
6362
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006363/* Test InputDispatcher for MultiDisplay */
6364class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
6365public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006366 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006367 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08006368
Chris Yea209fde2020-07-22 13:54:51 -07006369 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006370 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006371 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006372
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006373 // Set focus window for primary display, but focused display would be second one.
6374 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07006375 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006376 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
6377
Vishnu Nair958da932020-08-21 17:12:37 -07006378 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006379 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08006380
Chris Yea209fde2020-07-22 13:54:51 -07006381 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006382 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006383 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006384 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006385 // Set focus display to second one.
6386 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
6387 // Set focus window for second display.
6388 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07006389 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006390 mDispatcher->onWindowInfosChanged(
6391 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006392 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006393 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006394 }
6395
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006396 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006397 InputDispatcherTest::TearDown();
6398
Chris Yea209fde2020-07-22 13:54:51 -07006399 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006400 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07006401 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006402 windowInSecondary.clear();
6403 }
6404
6405protected:
Chris Yea209fde2020-07-22 13:54:51 -07006406 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006407 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07006408 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006409 sp<FakeWindowHandle> windowInSecondary;
6410};
6411
6412TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
6413 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006416 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006417 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08006418 windowInSecondary->assertNoEvents();
6419
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006420 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006422 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006423 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006424 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006425 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08006426}
6427
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006428TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08006429 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006431 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006432 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006433 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08006434 windowInSecondary->assertNoEvents();
6435
6436 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006438 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08006439 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006440 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006441
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006442 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006443 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08006444
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006445 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006446 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006447 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006448
6449 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006450 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08006451 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006452 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006453 windowInSecondary->assertNoEvents();
6454}
6455
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006456// Test per-display input monitors for motion event.
6457TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006458 FakeMonitorReceiver monitorInPrimary =
6459 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6460 FakeMonitorReceiver monitorInSecondary =
6461 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006462
6463 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006465 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006467 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006468 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006469 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006470 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006471
6472 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006474 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006476 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006477 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006478 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006479 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006480
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006481 // Lift up the touch from the second display
6482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006483 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006484 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6485 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6486 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6487
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006488 // Test inject a non-pointer motion event.
6489 // If specific a display, it will dispatch to the focused window of particular display,
6490 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006492 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006493 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006494 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006495 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006496 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006497 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006498}
6499
6500// Test per-display input monitors for key event.
6501TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006502 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006503 FakeMonitorReceiver monitorInPrimary =
6504 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6505 FakeMonitorReceiver monitorInSecondary =
6506 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006507
6508 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006510 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006511 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006512 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006513 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006514 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006515}
6516
Vishnu Nair958da932020-08-21 17:12:37 -07006517TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6518 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006519 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006520 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006521 mDispatcher->onWindowInfosChanged(
6522 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
6523 *windowInSecondary->getInfo()},
6524 {},
6525 0,
6526 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006527 setFocusedWindow(secondWindowInPrimary);
6528 windowInPrimary->consumeFocusEvent(false);
6529 secondWindowInPrimary->consumeFocusEvent(true);
6530
6531 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6533 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006534 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006535 windowInPrimary->assertNoEvents();
6536 windowInSecondary->assertNoEvents();
6537 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6538}
6539
Arthur Hungdfd528e2021-12-08 13:23:04 +00006540TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6541 FakeMonitorReceiver monitorInPrimary =
6542 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6543 FakeMonitorReceiver monitorInSecondary =
6544 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6545
6546 // Test touch down on primary display.
6547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006548 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006549 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6550 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6551 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6552
6553 // Test touch down on second display.
6554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006555 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00006556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6557 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6558 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6559
6560 // Trigger cancel touch.
6561 mDispatcher->cancelCurrentTouch();
6562 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6563 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6564 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6565 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6566
6567 // Test inject a move motion event, no window/monitor should receive the event.
6568 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006569 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006570 ADISPLAY_ID_DEFAULT, {110, 200}))
6571 << "Inject motion event should return InputEventInjectionResult::FAILED";
6572 windowInPrimary->assertNoEvents();
6573 monitorInPrimary.assertNoEvents();
6574
6575 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006576 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00006577 SECOND_DISPLAY_ID, {110, 200}))
6578 << "Inject motion event should return InputEventInjectionResult::FAILED";
6579 windowInSecondary->assertNoEvents();
6580 monitorInSecondary.assertNoEvents();
6581}
6582
Jackal Guof9696682018-10-05 12:23:23 +08006583class InputFilterTest : public InputDispatcherTest {
6584protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006585 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6586 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006587 NotifyMotionArgs motionArgs;
6588
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006589 motionArgs =
6590 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006591 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006592 motionArgs =
6593 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006594 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006595 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006596 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006597 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006598 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006599 } else {
6600 mFakePolicy->assertFilterInputEventWasNotCalled();
6601 }
6602 }
6603
6604 void testNotifyKey(bool expectToBeFiltered) {
6605 NotifyKeyArgs keyArgs;
6606
6607 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006608 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006609 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006610 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006611 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006612
6613 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006614 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006615 } else {
6616 mFakePolicy->assertFilterInputEventWasNotCalled();
6617 }
6618 }
6619};
6620
6621// Test InputFilter for MotionEvent
6622TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6623 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006624 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6625 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006626
6627 // Enable InputFilter
6628 mDispatcher->setInputFilterEnabled(true);
6629 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006630 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6631 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006632
6633 // Disable InputFilter
6634 mDispatcher->setInputFilterEnabled(false);
6635 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006636 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6637 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006638}
6639
6640// Test InputFilter for KeyEvent
6641TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6642 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006643 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006644
6645 // Enable InputFilter
6646 mDispatcher->setInputFilterEnabled(true);
6647 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006648 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006649
6650 // Disable InputFilter
6651 mDispatcher->setInputFilterEnabled(false);
6652 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006653 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006654}
6655
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006656// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6657// logical display coordinate space.
6658TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6659 ui::Transform firstDisplayTransform;
6660 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6661 ui::Transform secondDisplayTransform;
6662 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6663
6664 std::vector<gui::DisplayInfo> displayInfos(2);
6665 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6666 displayInfos[0].transform = firstDisplayTransform;
6667 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6668 displayInfos[1].transform = secondDisplayTransform;
6669
Patrick Williamsd828f302023-04-28 17:52:08 -05006670 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006671
6672 // Enable InputFilter
6673 mDispatcher->setInputFilterEnabled(true);
6674
6675 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006676 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6677 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006678}
6679
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006680class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6681protected:
6682 virtual void SetUp() override {
6683 InputDispatcherTest::SetUp();
6684
6685 /**
6686 * We don't need to enable input filter to test the injected event policy, but we enabled it
6687 * here to make the tests more realistic, since this policy only matters when inputfilter is
6688 * on.
6689 */
6690 mDispatcher->setInputFilterEnabled(true);
6691
6692 std::shared_ptr<InputApplicationHandle> application =
6693 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006694 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6695 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006696
6697 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6698 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006699 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006700 setFocusedWindow(mWindow);
6701 mWindow->consumeFocusEvent(true);
6702 }
6703
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006704 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6705 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006706 KeyEvent event;
6707
6708 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6709 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6710 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006711 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006712 const int32_t additionalPolicyFlags =
6713 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006715 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006716 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006717 policyFlags | additionalPolicyFlags));
6718
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006719 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006720 }
6721
6722 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6723 int32_t flags) {
6724 MotionEvent event;
6725 PointerProperties pointerProperties[1];
6726 PointerCoords pointerCoords[1];
6727 pointerProperties[0].clear();
6728 pointerProperties[0].id = 0;
6729 pointerCoords[0].clear();
6730 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6731 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6732
6733 ui::Transform identityTransform;
6734 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6735 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6736 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6737 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6738 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006739 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006740 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006741 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006742
6743 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006745 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006746 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006747 policyFlags | additionalPolicyFlags));
6748
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006749 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006750 }
6751
6752private:
6753 sp<FakeWindowHandle> mWindow;
6754};
6755
6756TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006757 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6758 // filter. Without it, the event will no different from a regularly injected event, and the
6759 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006760 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6761 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006762}
6763
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006764TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006765 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006766 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006767 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6768}
6769
6770TEST_F(InputFilterInjectionPolicyTest,
6771 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6772 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006773 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006774 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006775}
6776
6777TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006778 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6779 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006780}
6781
chaviwfd6d3512019-03-25 13:23:49 -07006782class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006783 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006784 InputDispatcherTest::SetUp();
6785
Chris Yea209fde2020-07-22 13:54:51 -07006786 std::shared_ptr<FakeApplicationHandle> application =
6787 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006788 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006789 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006790 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006791
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006792 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006793 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006794 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006795
6796 // Set focused application.
6797 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006798 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006799
6800 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006801 mDispatcher->onWindowInfosChanged(
6802 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006803 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006804 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006805 }
6806
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006807 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006808 InputDispatcherTest::TearDown();
6809
6810 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006811 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006812 }
6813
6814protected:
6815 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006816 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006817 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006818};
6819
6820// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6821// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6822// the onPointerDownOutsideFocus callback.
6823TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006826 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006828 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006829
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006830 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006831 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6832}
6833
6834// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6835// DOWN on the window that doesn't have focus. Ensure no window received the
6836// onPointerDownOutsideFocus callback.
6837TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
6840 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006842 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006843
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006844 ASSERT_TRUE(mDispatcher->waitForIdle());
6845 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006846}
6847
6848// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6849// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6850TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006852 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006853 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006854 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006855
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006856 ASSERT_TRUE(mDispatcher->waitForIdle());
6857 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006858}
6859
6860// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6861// DOWN on the window that already has focus. Ensure no window received the
6862// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006863TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006865 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006866 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006868 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006869
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006870 ASSERT_TRUE(mDispatcher->waitForIdle());
6871 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006872}
6873
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006874// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6875// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6876TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6877 const MotionEvent event =
6878 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6879 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006880 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006881 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6882 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6885 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6886
6887 ASSERT_TRUE(mDispatcher->waitForIdle());
6888 mFakePolicy->assertOnPointerDownWasNotCalled();
6889 // Ensure that the unfocused window did not receive any FOCUS events.
6890 mUnfocusedWindow->assertNoEvents();
6891}
6892
chaviwaf87b3e2019-10-01 16:59:28 -07006893// These tests ensures we can send touch events to a single client when there are multiple input
6894// windows that point to the same client token.
6895class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6896 virtual void SetUp() override {
6897 InputDispatcherTest::SetUp();
6898
Chris Yea209fde2020-07-22 13:54:51 -07006899 std::shared_ptr<FakeApplicationHandle> application =
6900 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006901 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6902 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006903 mWindow1->setFrame(Rect(0, 0, 100, 100));
6904
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006905 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6906 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006907 mWindow2->setFrame(Rect(100, 100, 200, 200));
6908
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006909 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006910 }
6911
6912protected:
6913 sp<FakeWindowHandle> mWindow1;
6914 sp<FakeWindowHandle> mWindow2;
6915
6916 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006917 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006918 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6919 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006920 }
6921
6922 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6923 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006924 const std::string name = window->getName();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006925 MotionEvent* motionEvent = window->consumeMotion();
chaviwaf87b3e2019-10-01 16:59:28 -07006926
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006927 ASSERT_NE(nullptr, motionEvent)
6928 << name.c_str() << ": consumer should have returned non-NULL event.";
chaviwaf87b3e2019-10-01 16:59:28 -07006929
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07006930 ASSERT_THAT(*motionEvent, WithMotionAction(expectedAction));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006931 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006932
6933 for (size_t i = 0; i < points.size(); i++) {
6934 float expectedX = points[i].x;
6935 float expectedY = points[i].y;
6936
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006937 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006938 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006939 << ", got " << motionEvent->getX(i);
6940 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07006941 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006942 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07006943 }
6944 }
chaviw9eaa22c2020-07-01 16:21:27 -07006945
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006946 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006947 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006948 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6949 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006950
6951 // Always consume from window1 since it's the window that has the InputReceiver
6952 consumeMotionEvent(mWindow1, action, expectedPoints);
6953 }
chaviwaf87b3e2019-10-01 16:59:28 -07006954};
6955
6956TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6957 // Touch Window 1
6958 PointF touchedPoint = {10, 10};
6959 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006960 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006961
6962 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006963 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006964
6965 // Touch Window 2
6966 touchedPoint = {150, 150};
6967 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006968 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006969}
6970
chaviw9eaa22c2020-07-01 16:21:27 -07006971TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6972 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006973 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006974 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07006975
6976 // Touch Window 1
6977 PointF touchedPoint = {10, 10};
6978 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006979 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006980 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006981 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006982
6983 // Touch Window 2
6984 touchedPoint = {150, 150};
6985 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006986 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6987 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006988
chaviw9eaa22c2020-07-01 16:21:27 -07006989 // Update the transform so rotation is set
6990 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006991 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07006992 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6993 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006994}
6995
chaviw9eaa22c2020-07-01 16:21:27 -07006996TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006997 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006998 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006999
7000 // Touch Window 1
7001 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7002 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007003 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007004
7005 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007006 touchedPoints.push_back(PointF{150, 150});
7007 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007008 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007009
chaviw9eaa22c2020-07-01 16:21:27 -07007010 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007011 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007012 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007013
chaviw9eaa22c2020-07-01 16:21:27 -07007014 // Update the transform so rotation is set for Window 2
7015 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007016 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007017 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007018 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007019}
7020
chaviw9eaa22c2020-07-01 16:21:27 -07007021TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007022 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007023 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007024
7025 // Touch Window 1
7026 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7027 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007028 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007029
7030 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007031 touchedPoints.push_back(PointF{150, 150});
7032 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007033
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007034 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007035
7036 // Move both windows
7037 touchedPoints = {{20, 20}, {175, 175}};
7038 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7039 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7040
chaviw9eaa22c2020-07-01 16:21:27 -07007041 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007042
chaviw9eaa22c2020-07-01 16:21:27 -07007043 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007044 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007045 expectedPoints.pop_back();
7046
7047 // Touch Window 2
7048 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007049 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007050 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007051 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007052
7053 // Move both windows
7054 touchedPoints = {{20, 20}, {175, 175}};
7055 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7056 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7057
7058 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007059}
7060
7061TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7062 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007063 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007064
7065 // Touch Window 1
7066 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7067 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007068 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007069
7070 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007071 touchedPoints.push_back(PointF{150, 150});
7072 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007073
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007074 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007075
7076 // Move both windows
7077 touchedPoints = {{20, 20}, {175, 175}};
7078 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7079 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7080
chaviw9eaa22c2020-07-01 16:21:27 -07007081 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007082}
7083
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007084/**
7085 * When one of the windows is slippery, the touch should not slip into the other window with the
7086 * same input channel.
7087 */
7088TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7089 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007090 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007091
7092 // Touch down in window 1
7093 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7094 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7095 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7096
7097 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7098 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7099 // getting generated.
7100 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7101 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7102
7103 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7104}
7105
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007106/**
7107 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7108 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7109 * that the pointer is hovering over may have a different transform.
7110 */
7111TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007112 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007113
7114 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007115 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7116 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7117 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007118 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7119 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007120 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7122 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7123 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007124 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7125 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7126 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7127}
7128
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007129class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7130 virtual void SetUp() override {
7131 InputDispatcherTest::SetUp();
7132
Chris Yea209fde2020-07-22 13:54:51 -07007133 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007134 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007135 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7136 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007137 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007138 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007139 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007140
7141 // Set focused application.
7142 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7143
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007144 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007145 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007146 mWindow->consumeFocusEvent(true);
7147 }
7148
7149 virtual void TearDown() override {
7150 InputDispatcherTest::TearDown();
7151 mWindow.clear();
7152 }
7153
7154protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007155 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007156 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007157 sp<FakeWindowHandle> mWindow;
7158 static constexpr PointF WINDOW_LOCATION = {20, 20};
7159
7160 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007162 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007163 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007165 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007166 WINDOW_LOCATION));
7167 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007168
7169 sp<FakeWindowHandle> addSpyWindow() {
7170 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007171 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007172 spy->setTrustedOverlay(true);
7173 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007174 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007175 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007176 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007177 return spy;
7178 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007179};
7180
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007181// Send a tap and respond, which should not cause an ANR.
7182TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7183 tapOnWindow();
7184 mWindow->consumeMotionDown();
7185 mWindow->consumeMotionUp();
7186 ASSERT_TRUE(mDispatcher->waitForIdle());
7187 mFakePolicy->assertNotifyAnrWasNotCalled();
7188}
7189
7190// Send a regular key and respond, which should not cause an ANR.
7191TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007193 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7194 ASSERT_TRUE(mDispatcher->waitForIdle());
7195 mFakePolicy->assertNotifyAnrWasNotCalled();
7196}
7197
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007198TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7199 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007200 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007201 mWindow->consumeFocusEvent(false);
7202
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007203 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007204 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7205 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007206 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007208 // Key will not go to window because we have no focused window.
7209 // The 'no focused window' ANR timer should start instead.
7210
7211 // Now, the focused application goes away.
7212 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7213 // The key should get dropped and there should be no ANR.
7214
7215 ASSERT_TRUE(mDispatcher->waitForIdle());
7216 mFakePolicy->assertNotifyAnrWasNotCalled();
7217}
7218
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007219// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007220// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7221// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007222TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007224 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007225 WINDOW_LOCATION));
7226
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007227 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7228 ASSERT_TRUE(sequenceNum);
7229 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007230 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007231
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007232 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007233 mWindow->consumeMotionEvent(
7234 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007235 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007236 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007237}
7238
7239// Send a key to the app and have the app not respond right away.
7240TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7241 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007243 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7244 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007245 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007246 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007247 ASSERT_TRUE(mDispatcher->waitForIdle());
7248}
7249
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007250// We have a focused application, but no focused window
7251TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007252 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007253 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007254 mWindow->consumeFocusEvent(false);
7255
7256 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007259 WINDOW_LOCATION));
7260 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
7261 mDispatcher->waitForIdle();
7262 mFakePolicy->assertNotifyAnrWasNotCalled();
7263
7264 // Once a focused event arrives, we get an ANR for this application
7265 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7266 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007267 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007268 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007269 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007270 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007271 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07007272 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007273 ASSERT_TRUE(mDispatcher->waitForIdle());
7274}
7275
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007276/**
7277 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
7278 * there will not be an ANR.
7279 */
7280TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
7281 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007282 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007283 mWindow->consumeFocusEvent(false);
7284
7285 KeyEvent event;
7286 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
7287 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
7288
7289 // Define a valid key down event that is stale (too old).
7290 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007291 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00007292 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007293
7294 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
7295
7296 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007297 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08007298 InputEventInjectionSync::WAIT_FOR_RESULT,
7299 INJECT_EVENT_TIMEOUT, policyFlags);
7300 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
7301 << "Injection should fail because the event is stale";
7302
7303 ASSERT_TRUE(mDispatcher->waitForIdle());
7304 mFakePolicy->assertNotifyAnrWasNotCalled();
7305 mWindow->assertNoEvents();
7306}
7307
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007308// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007309// Make sure that we don't notify policy twice about the same ANR.
7310TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007311 const std::chrono::duration appTimeout = 400ms;
7312 mApplication->setDispatchingTimeout(appTimeout);
7313 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7314
Vishnu Nair47074b82020-08-14 11:54:47 -07007315 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007316 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007317 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007318
7319 // Once a focused event arrives, we get an ANR for this application
7320 // We specify the injection timeout to be smaller than the application timeout, to ensure that
7321 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007322 const std::chrono::duration eventInjectionTimeout = 100ms;
7323 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007324 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007325 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07007326 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
7327 /*allowKeyRepeat=*/false);
7328 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
7329 << "result=" << ftl::enum_string(result);
7330 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
7331 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
7332 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
7333 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007334
Vishnu Naire4df8752022-09-08 09:17:55 -07007335 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007336 // ANR should not be raised again. It is up to policy to do that if it desires.
7337 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007338
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007339 // If we now get a focused window, the ANR should stop, but the policy handles that via
7340 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007341 ASSERT_TRUE(mDispatcher->waitForIdle());
7342}
7343
7344// We have a focused application, but no focused window
7345TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07007346 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007347 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007348 mWindow->consumeFocusEvent(false);
7349
7350 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007351 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007352
Vishnu Naire4df8752022-09-08 09:17:55 -07007353 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7354 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007355
7356 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007357 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007358 ASSERT_TRUE(mDispatcher->waitForIdle());
7359 mWindow->assertNoEvents();
7360}
7361
7362/**
7363 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
7364 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
7365 * If we process 1 of the events, but ANR on the second event with the same timestamp,
7366 * the ANR mechanism should still work.
7367 *
7368 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
7369 * DOWN event, while not responding on the second one.
7370 */
7371TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
7372 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007373 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007374 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7375 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7376 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007377 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007378
7379 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007380 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007381 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
7382 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
7383 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007384 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007385
7386 // We have now sent down and up. Let's consume first event and then ANR on the second.
7387 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7388 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007389 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007390}
7391
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007392// A spy window can receive an ANR
7393TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
7394 sp<FakeWindowHandle> spy = addSpyWindow();
7395
7396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007397 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007398 WINDOW_LOCATION));
7399 mWindow->consumeMotionDown();
7400
7401 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
7402 ASSERT_TRUE(sequenceNum);
7403 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007404 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007405
7406 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007407 spy->consumeMotionEvent(
7408 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007409 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007410 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007411}
7412
7413// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007414// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007415TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
7416 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007417
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007419 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007420 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007422
7423 // Stuck on the ACTION_UP
7424 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007425 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007426
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007427 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007428 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007429 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7430 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007431
7432 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7433 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007434 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007435 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007436 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007437}
7438
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007439// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007440// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007441TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
7442 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007443
7444 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007445 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7446 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007447
7448 mWindow->consumeMotionDown();
7449 // Stuck on the ACTION_UP
7450 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007451 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007452
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007453 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007454 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007455 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7456 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007457
7458 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7459 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007460 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007461 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007462 spy->assertNoEvents();
7463}
7464
7465TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007466 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007467
7468 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7469
7470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007471 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007472 WINDOW_LOCATION));
7473
7474 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7475 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7476 ASSERT_TRUE(consumeSeq);
7477
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007478 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
7479 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007480
7481 monitor.finishEvent(*consumeSeq);
7482 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7483
7484 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007485 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007486}
7487
7488// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7489// process events, you don't get an anr. When the window later becomes unresponsive again, you
7490// get an ANR again.
7491// 1. tap -> block on ACTION_UP -> receive ANR
7492// 2. consume all pending events (= queue becomes healthy again)
7493// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7494TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7495 tapOnWindow();
7496
7497 mWindow->consumeMotionDown();
7498 // Block on ACTION_UP
7499 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007500 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007501 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7502 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007503 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007504 mWindow->assertNoEvents();
7505
7506 tapOnWindow();
7507 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007508 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007509 mWindow->consumeMotionUp();
7510
7511 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007512 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007513 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007514 mWindow->assertNoEvents();
7515}
7516
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007517// If a connection remains unresponsive for a while, make sure policy is only notified once about
7518// it.
7519TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007521 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007522 WINDOW_LOCATION));
7523
7524 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007525 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007526 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007527 // 'notifyConnectionUnresponsive' should only be called once per connection
7528 mFakePolicy->assertNotifyAnrWasNotCalled();
7529 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007530 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007531 mWindow->consumeMotionEvent(
7532 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007533 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007534 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007535 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007536 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007537}
7538
7539/**
7540 * 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 -07007541 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007542 *
7543 * Warning!!!
7544 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7545 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007546 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007547 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7548 *
7549 * If that value changes, this test should also change.
7550 */
7551TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7552 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007553 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007554
7555 tapOnWindow();
7556 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7557 ASSERT_TRUE(downSequenceNum);
7558 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7559 ASSERT_TRUE(upSequenceNum);
7560 // Don't finish the events yet, and send a key
7561 // Injection will "succeed" because we will eventually give up and send the key to the focused
7562 // window even if motions are still being processed. But because the injection timeout is short,
7563 // we will receive INJECTION_TIMED_OUT as the result.
7564
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007565 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007566 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7567 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007568 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007569 // Key will not be sent to the window, yet, because the window is still processing events
7570 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007571 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
7572 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7573 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7574 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007575
7576 std::this_thread::sleep_for(500ms);
7577 // if we wait long enough though, dispatcher will give up, and still send the key
7578 // to the focused window, even though we have not yet finished the motion event
7579 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7580 mWindow->finishEvent(*downSequenceNum);
7581 mWindow->finishEvent(*upSequenceNum);
7582}
7583
7584/**
7585 * If a window is processing a motion event, and then a key event comes in, the key event should
7586 * not go to the focused window until the motion is processed.
7587 * If then a new motion comes in, then the pending key event should be going to the currently
7588 * focused window right away.
7589 */
7590TEST_F(InputDispatcherSingleWindowAnr,
7591 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7592 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007593 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007594
7595 tapOnWindow();
7596 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7597 ASSERT_TRUE(downSequenceNum);
7598 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7599 ASSERT_TRUE(upSequenceNum);
7600 // Don't finish the events yet, and send a key
7601 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007603 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
7604 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007605 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007606 // Make sure the `assertNoEvents` check doesn't take too long. It uses
7607 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
7608 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7609 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007610
7611 // Now tap down again. It should cause the pending key to go to the focused window right away.
7612 tapOnWindow();
7613 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7614 // the other events yet. We can finish events in any order.
7615 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7616 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7617 mWindow->consumeMotionDown();
7618 mWindow->consumeMotionUp();
7619 mWindow->assertNoEvents();
7620}
7621
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007622/**
7623 * Send an event to the app and have the app not respond right away.
7624 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7625 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7626 * At some point, the window becomes responsive again.
7627 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7628 */
7629TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7631 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7632 .build());
7633
7634 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7635 ASSERT_TRUE(sequenceNum);
7636 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7637 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7638
7639 mWindow->finishEvent(*sequenceNum);
7640 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7641 ASSERT_TRUE(mDispatcher->waitForIdle());
7642 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7643
7644 // Now that the window is responsive, let's continue the gesture.
7645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7646 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7647 .build());
7648
7649 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7650 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7651 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7652 .build());
7653
7654 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7655 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7656 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7657 .build());
7658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7659 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7660 .build());
7661 // We already canceled this pointer, so the window shouldn't get any new events.
7662 mWindow->assertNoEvents();
7663
7664 // Start another one.
7665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7666 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7667 .build());
7668 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7669}
7670
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007671class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7672 virtual void SetUp() override {
7673 InputDispatcherTest::SetUp();
7674
Chris Yea209fde2020-07-22 13:54:51 -07007675 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007676 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007677 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7678 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007679 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007680 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007681 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007682
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007683 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7684 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007685 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007686 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007687
7688 // Set focused application.
7689 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007690 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007691
7692 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007693 mDispatcher->onWindowInfosChanged(
7694 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007695 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007696 mFocusedWindow->consumeFocusEvent(true);
7697 }
7698
7699 virtual void TearDown() override {
7700 InputDispatcherTest::TearDown();
7701
7702 mUnfocusedWindow.clear();
7703 mFocusedWindow.clear();
7704 }
7705
7706protected:
Chris Yea209fde2020-07-22 13:54:51 -07007707 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007708 sp<FakeWindowHandle> mUnfocusedWindow;
7709 sp<FakeWindowHandle> mFocusedWindow;
7710 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7711 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7712 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7713
7714 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7715
7716 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7717
7718private:
7719 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007722 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007724 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007725 location));
7726 }
7727};
7728
7729// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7730// should be ANR'd first.
7731TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007733 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007734 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007735 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007736 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007737 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007738 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007739 // We consumed all events, so no ANR
7740 ASSERT_TRUE(mDispatcher->waitForIdle());
7741 mFakePolicy->assertNotifyAnrWasNotCalled();
7742
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007744 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007745 FOCUSED_WINDOW_LOCATION));
7746 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7747 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007748
7749 const std::chrono::duration timeout =
7750 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007751 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007752 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7753 // sequence to make it consistent
7754 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007755 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007756 mFocusedWindow->consumeMotionDown();
7757 // This cancel is generated because the connection was unresponsive
7758 mFocusedWindow->consumeMotionCancel();
7759 mFocusedWindow->assertNoEvents();
7760 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007761 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007762 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7763 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007764 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007765}
7766
7767// If we have 2 windows with identical timeouts that are both unresponsive,
7768// it doesn't matter which order they should have ANR.
7769// But we should receive ANR for both.
7770TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7771 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007772 mUnfocusedWindow->setDispatchingTimeout(
7773 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007774 mDispatcher->onWindowInfosChanged(
7775 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007776
7777 tapOnFocusedWindow();
7778 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007779 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007780 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7781 mFocusedWindow->getDispatchingTimeout(
7782 DISPATCHING_TIMEOUT)),
7783 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7784
7785 ASSERT_THAT(anrConnectionTokens,
7786 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7787 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007788
7789 ASSERT_TRUE(mDispatcher->waitForIdle());
7790 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007791
7792 mFocusedWindow->consumeMotionDown();
7793 mFocusedWindow->consumeMotionUp();
7794 mUnfocusedWindow->consumeMotionOutside();
7795
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007796 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7797 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007798
7799 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007800 ASSERT_THAT(responsiveTokens,
7801 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7802 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007803 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007804}
7805
7806// If a window is already not responding, the second tap on the same window should be ignored.
7807// We should also log an error to account for the dropped event (not tested here).
7808// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7809TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7810 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007811 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007812 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007813 // Receive the events, but don't respond
7814 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7815 ASSERT_TRUE(downEventSequenceNum);
7816 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7817 ASSERT_TRUE(upEventSequenceNum);
7818 const std::chrono::duration timeout =
7819 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007820 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007821
7822 // Tap once again
7823 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007824 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007826 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007827 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007828 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007829 FOCUSED_WINDOW_LOCATION));
7830 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7831 // valid touch target
7832 mUnfocusedWindow->assertNoEvents();
7833
7834 // Consume the first tap
7835 mFocusedWindow->finishEvent(*downEventSequenceNum);
7836 mFocusedWindow->finishEvent(*upEventSequenceNum);
7837 ASSERT_TRUE(mDispatcher->waitForIdle());
7838 // The second tap did not go to the focused window
7839 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007840 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007841 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7842 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007843 mFakePolicy->assertNotifyAnrWasNotCalled();
7844}
7845
7846// If you tap outside of all windows, there will not be ANR
7847TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007848 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007849 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007850 LOCATION_OUTSIDE_ALL_WINDOWS));
7851 ASSERT_TRUE(mDispatcher->waitForIdle());
7852 mFakePolicy->assertNotifyAnrWasNotCalled();
7853}
7854
7855// Since the focused window is paused, tapping on it should not produce any events
7856TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7857 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007858 mDispatcher->onWindowInfosChanged(
7859 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007860
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007861 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007862 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007863 FOCUSED_WINDOW_LOCATION));
7864
7865 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7866 ASSERT_TRUE(mDispatcher->waitForIdle());
7867 // Should not ANR because the window is paused, and touches shouldn't go to it
7868 mFakePolicy->assertNotifyAnrWasNotCalled();
7869
7870 mFocusedWindow->assertNoEvents();
7871 mUnfocusedWindow->assertNoEvents();
7872}
7873
7874/**
7875 * 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 -07007876 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007877 * If a different window becomes focused at this time, the key should go to that window instead.
7878 *
7879 * Warning!!!
7880 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7881 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007882 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007883 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7884 *
7885 * If that value changes, this test should also change.
7886 */
7887TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7888 // Set a long ANR timeout to prevent it from triggering
7889 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007890 mDispatcher->onWindowInfosChanged(
7891 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007892
7893 tapOnUnfocusedWindow();
7894 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7895 ASSERT_TRUE(downSequenceNum);
7896 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7897 ASSERT_TRUE(upSequenceNum);
7898 // Don't finish the events yet, and send a key
7899 // Injection will succeed because we will eventually give up and send the key to the focused
7900 // window even if motions are still being processed.
7901
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007902 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007903 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7904 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007906 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007907 // and the key remains pending, waiting for the touch events to be processed.
7908 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
7909 // under the hood.
7910 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
7911 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007912
7913 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007914 mFocusedWindow->setFocusable(false);
7915 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007916 mDispatcher->onWindowInfosChanged(
7917 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007918 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007919
7920 // Focus events should precede the key events
7921 mUnfocusedWindow->consumeFocusEvent(true);
7922 mFocusedWindow->consumeFocusEvent(false);
7923
7924 // Finish the tap events, which should unblock dispatcher
7925 mUnfocusedWindow->finishEvent(*downSequenceNum);
7926 mUnfocusedWindow->finishEvent(*upSequenceNum);
7927
7928 // Now that all queues are cleared and no backlog in the connections, the key event
7929 // can finally go to the newly focused "mUnfocusedWindow".
7930 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7931 mFocusedWindow->assertNoEvents();
7932 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007933 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007934}
7935
7936// When the touch stream is split across 2 windows, and one of them does not respond,
7937// then ANR should be raised and the touch should be canceled for the unresponsive window.
7938// The other window should not be affected by that.
7939TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7940 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007941 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7942 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7943 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007944 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007945 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007946
7947 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007948 mDispatcher->notifyMotion(
7949 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7950 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007951
7952 const std::chrono::duration timeout =
7953 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007954 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007955
7956 mUnfocusedWindow->consumeMotionDown();
7957 mFocusedWindow->consumeMotionDown();
7958 // Focused window may or may not receive ACTION_MOVE
7959 // But it should definitely receive ACTION_CANCEL due to the ANR
7960 InputEvent* event;
7961 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7962 ASSERT_TRUE(moveOrCancelSequenceNum);
7963 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7964 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007965 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007966 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7967 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7968 mFocusedWindow->consumeMotionCancel();
7969 } else {
7970 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7971 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007972 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007973 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7974 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007975
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007976 mUnfocusedWindow->assertNoEvents();
7977 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007978 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007979}
7980
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007981/**
7982 * If we have no focused window, and a key comes in, we start the ANR timer.
7983 * The focused application should add a focused window before the timer runs out to prevent ANR.
7984 *
7985 * If the user touches another application during this time, the key should be dropped.
7986 * Next, if a new focused window comes in, without toggling the focused application,
7987 * then no ANR should occur.
7988 *
7989 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7990 * but in some cases the policy may not update the focused application.
7991 */
7992TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7993 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7994 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07007995 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007996 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7997 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7998 mFocusedWindow->setFocusable(false);
7999
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008000 mDispatcher->onWindowInfosChanged(
8001 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008002 mFocusedWindow->consumeFocusEvent(false);
8003
8004 // Send a key. The ANR timer should start because there is no focused window.
8005 // 'focusedApplication' will get blamed if this timer completes.
8006 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008007 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008008 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8009 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008010 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008012
8013 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8014 // then the injected touches won't cause the focused event to get dropped.
8015 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8016 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8017 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8018 // For this test, it means that the key would get delivered to the window once it becomes
8019 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008020 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008021
8022 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008023 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8024 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8025 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008026
8027 // We do not consume the motion right away, because that would require dispatcher to first
8028 // process (== drop) the key event, and by that time, ANR will be raised.
8029 // Set the focused window first.
8030 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008031 mDispatcher->onWindowInfosChanged(
8032 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008033 setFocusedWindow(mFocusedWindow);
8034 mFocusedWindow->consumeFocusEvent(true);
8035 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8036 // to another application. This could be a bug / behaviour in the policy.
8037
8038 mUnfocusedWindow->consumeMotionDown();
8039
8040 ASSERT_TRUE(mDispatcher->waitForIdle());
8041 // Should not ANR because we actually have a focused window. It was just added too slowly.
8042 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8043}
8044
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008045// These tests ensure we cannot send touch events to a window that's positioned behind a window
8046// that has feature NO_INPUT_CHANNEL.
8047// Layout:
8048// Top (closest to user)
8049// mNoInputWindow (above all windows)
8050// mBottomWindow
8051// Bottom (furthest from user)
8052class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8053 virtual void SetUp() override {
8054 InputDispatcherTest::SetUp();
8055
8056 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008057 mNoInputWindow =
8058 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8059 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008060 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008061 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008062 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8063 // It's perfectly valid for this window to not have an associated input channel
8064
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008065 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8066 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008067 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8068
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008069 mDispatcher->onWindowInfosChanged(
8070 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008071 }
8072
8073protected:
8074 std::shared_ptr<FakeApplicationHandle> mApplication;
8075 sp<FakeWindowHandle> mNoInputWindow;
8076 sp<FakeWindowHandle> mBottomWindow;
8077};
8078
8079TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8080 PointF touchedPoint = {10, 10};
8081
Prabir Pradhan678438e2023-04-13 19:32:51 +00008082 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8083 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8084 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008085
8086 mNoInputWindow->assertNoEvents();
8087 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8088 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8089 // and therefore should prevent mBottomWindow from receiving touches
8090 mBottomWindow->assertNoEvents();
8091}
8092
8093/**
8094 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8095 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8096 */
8097TEST_F(InputDispatcherMultiWindowOcclusionTests,
8098 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008099 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8100 "Window with input channel and NO_INPUT_CHANNEL",
8101 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008102
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008103 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008104 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008105 mDispatcher->onWindowInfosChanged(
8106 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008107
8108 PointF touchedPoint = {10, 10};
8109
Prabir Pradhan678438e2023-04-13 19:32:51 +00008110 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8111 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8112 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008113
8114 mNoInputWindow->assertNoEvents();
8115 mBottomWindow->assertNoEvents();
8116}
8117
Vishnu Nair958da932020-08-21 17:12:37 -07008118class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8119protected:
8120 std::shared_ptr<FakeApplicationHandle> mApp;
8121 sp<FakeWindowHandle> mWindow;
8122 sp<FakeWindowHandle> mMirror;
8123
8124 virtual void SetUp() override {
8125 InputDispatcherTest::SetUp();
8126 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008127 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8128 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8129 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008130 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8131 mWindow->setFocusable(true);
8132 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008133 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008134 }
8135};
8136
8137TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8138 // Request focus on a mirrored window
8139 setFocusedWindow(mMirror);
8140
8141 // window gets focused
8142 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008144 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008145 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8146}
8147
8148// A focused & mirrored window remains focused only if the window and its mirror are both
8149// focusable.
8150TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8151 setFocusedWindow(mMirror);
8152
8153 // window gets focused
8154 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008156 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008157 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008159 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008160 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8161
8162 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008163 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008164
8165 // window loses focus since one of the windows associated with the token in not focusable
8166 mWindow->consumeFocusEvent(false);
8167
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008168 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008169 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008170 mWindow->assertNoEvents();
8171}
8172
8173// A focused & mirrored window remains focused until the window and its mirror both become
8174// invisible.
8175TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8176 setFocusedWindow(mMirror);
8177
8178 // window gets focused
8179 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008181 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008182 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008184 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008185 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8186
8187 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008188 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008189
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008191 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008192 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008194 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008195 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8196
8197 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008198 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008199
8200 // window loses focus only after all windows associated with the token become invisible.
8201 mWindow->consumeFocusEvent(false);
8202
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008203 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008204 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008205 mWindow->assertNoEvents();
8206}
8207
8208// A focused & mirrored window remains focused until both windows are removed.
8209TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8210 setFocusedWindow(mMirror);
8211
8212 // window gets focused
8213 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008215 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008216 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008218 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008219 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8220
8221 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008222 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008223
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008225 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008226 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008228 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008229 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8230
8231 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008232 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008233 mWindow->consumeFocusEvent(false);
8234
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008235 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008236 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008237 mWindow->assertNoEvents();
8238}
8239
8240// Focus request can be pending until one window becomes visible.
8241TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
8242 // Request focus on an invisible mirror.
8243 mWindow->setVisible(false);
8244 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008245 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008246 setFocusedWindow(mMirror);
8247
8248 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008250 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
8251 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008252
8253 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008254 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008255
8256 // window gets focused
8257 mWindow->consumeFocusEvent(true);
8258 // window gets the pending key event
8259 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8260}
Prabir Pradhan99987712020-11-10 18:43:05 -08008261
8262class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
8263protected:
8264 std::shared_ptr<FakeApplicationHandle> mApp;
8265 sp<FakeWindowHandle> mWindow;
8266 sp<FakeWindowHandle> mSecondWindow;
8267
8268 void SetUp() override {
8269 InputDispatcherTest::SetUp();
8270 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008271 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008272 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008273 mSecondWindow =
8274 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08008275 mSecondWindow->setFocusable(true);
8276
8277 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008278 mDispatcher->onWindowInfosChanged(
8279 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08008280
8281 setFocusedWindow(mWindow);
8282 mWindow->consumeFocusEvent(true);
8283 }
8284
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008285 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008286 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08008287 }
8288
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008289 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
8290 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08008291 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008292 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
8293 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008294 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008295 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08008296 }
8297};
8298
8299TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
8300 // Ensure that capture cannot be obtained for unfocused windows.
8301 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
8302 mFakePolicy->assertSetPointerCaptureNotCalled();
8303 mSecondWindow->assertNoEvents();
8304
8305 // Ensure that capture can be enabled from the focus window.
8306 requestAndVerifyPointerCapture(mWindow, true);
8307
8308 // Ensure that capture cannot be disabled from a window that does not have capture.
8309 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
8310 mFakePolicy->assertSetPointerCaptureNotCalled();
8311
8312 // Ensure that capture can be disabled from the window with capture.
8313 requestAndVerifyPointerCapture(mWindow, false);
8314}
8315
8316TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008317 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008318
8319 setFocusedWindow(mSecondWindow);
8320
8321 // Ensure that the capture disabled event was sent first.
8322 mWindow->consumeCaptureEvent(false);
8323 mWindow->consumeFocusEvent(false);
8324 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008325 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008326
8327 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008328 notifyPointerCaptureChanged({});
8329 notifyPointerCaptureChanged(request);
8330 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08008331 mWindow->assertNoEvents();
8332 mSecondWindow->assertNoEvents();
8333 mFakePolicy->assertSetPointerCaptureNotCalled();
8334}
8335
8336TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008337 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08008338
8339 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008340 notifyPointerCaptureChanged({});
8341 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08008342
8343 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008344 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08008345 mWindow->consumeCaptureEvent(false);
8346 mWindow->assertNoEvents();
8347}
8348
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008349TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
8350 requestAndVerifyPointerCapture(mWindow, true);
8351
8352 // The first window loses focus.
8353 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008354 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008355 mWindow->consumeCaptureEvent(false);
8356
8357 // Request Pointer Capture from the second window before the notification from InputReader
8358 // arrives.
8359 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008360 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008361
8362 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008363 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008364
8365 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008366 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08008367
8368 mSecondWindow->consumeFocusEvent(true);
8369 mSecondWindow->consumeCaptureEvent(true);
8370}
8371
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00008372TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
8373 // App repeatedly enables and disables capture.
8374 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8375 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8376 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8377 mFakePolicy->assertSetPointerCaptureCalled(false);
8378 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8379 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8380
8381 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
8382 // first request is now stale, this should do nothing.
8383 notifyPointerCaptureChanged(firstRequest);
8384 mWindow->assertNoEvents();
8385
8386 // InputReader notifies that the second request was enabled.
8387 notifyPointerCaptureChanged(secondRequest);
8388 mWindow->consumeCaptureEvent(true);
8389}
8390
Prabir Pradhan7092e262022-05-03 16:51:09 +00008391TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
8392 requestAndVerifyPointerCapture(mWindow, true);
8393
8394 // App toggles pointer capture off and on.
8395 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
8396 mFakePolicy->assertSetPointerCaptureCalled(false);
8397
8398 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
8399 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
8400
8401 // InputReader notifies that the latest "enable" request was processed, while skipping over the
8402 // preceding "disable" request.
8403 notifyPointerCaptureChanged(enableRequest);
8404
8405 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
8406 // any notifications.
8407 mWindow->assertNoEvents();
8408}
8409
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008410/**
8411 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
8412 * mouse movements don't affect the previous mouse hovering state.
8413 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
8414 * HOVER_MOVE events).
8415 */
8416TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
8417 // Mouse hover on the window
8418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
8419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8420 .build());
8421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8422 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
8423 .build());
8424
8425 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
8426 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
8427
8428 // Start pointer capture
8429 requestAndVerifyPointerCapture(mWindow, true);
8430
8431 // Send some relative mouse movements and receive them in the window.
8432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
8433 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
8434 .build());
8435 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
8436 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
8437
8438 // Stop pointer capture
8439 requestAndVerifyPointerCapture(mWindow, false);
8440
8441 // Continue hovering on the window
8442 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
8443 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
8444 .build());
8445 mWindow->consumeMotionEvent(
8446 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
8447
8448 mWindow->assertNoEvents();
8449}
8450
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008451class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
8452protected:
8453 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00008454
8455 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
8456 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
8457
8458 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
8459 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8460
8461 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
8462 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
8463 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
8464 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
8465 MAXIMUM_OBSCURING_OPACITY);
8466
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008467 static constexpr gui::Uid TOUCHED_APP_UID{10001};
8468 static constexpr gui::Uid APP_B_UID{10002};
8469 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008470
8471 sp<FakeWindowHandle> mTouchWindow;
8472
8473 virtual void SetUp() override {
8474 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008475 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008476 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
8477 }
8478
8479 virtual void TearDown() override {
8480 InputDispatcherTest::TearDown();
8481 mTouchWindow.clear();
8482 }
8483
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008484 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05008485 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008486 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008487 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008488 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008489 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008490 return window;
8491 }
8492
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008493 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008494 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
8495 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008496 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008497 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008498 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008499 return window;
8500 }
8501
8502 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008503 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8504 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8505 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008506 }
8507};
8508
8509TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008510 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008511 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008512 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008513
8514 touch();
8515
8516 mTouchWindow->assertNoEvents();
8517}
8518
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008519TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008520 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8521 const sp<FakeWindowHandle>& w =
8522 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008523 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008524
8525 touch();
8526
8527 mTouchWindow->assertNoEvents();
8528}
8529
8530TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008531 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8532 const sp<FakeWindowHandle>& w =
8533 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008534 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008535
8536 touch();
8537
8538 w->assertNoEvents();
8539}
8540
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008541TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008542 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008543 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008544
8545 touch();
8546
8547 mTouchWindow->consumeAnyMotionDown();
8548}
8549
8550TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008551 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008552 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008553 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008554 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008555
8556 touch({PointF{100, 100}});
8557
8558 mTouchWindow->consumeAnyMotionDown();
8559}
8560
8561TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008562 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008563 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008564 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008565
8566 touch();
8567
8568 mTouchWindow->consumeAnyMotionDown();
8569}
8570
8571TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8572 const sp<FakeWindowHandle>& w =
8573 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008574 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008575
8576 touch();
8577
8578 mTouchWindow->consumeAnyMotionDown();
8579}
8580
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008581TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8582 const sp<FakeWindowHandle>& w =
8583 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008584 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008585
8586 touch();
8587
8588 w->assertNoEvents();
8589}
8590
8591/**
8592 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8593 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8594 * window, the occluding window will still receive ACTION_OUTSIDE event.
8595 */
8596TEST_F(InputDispatcherUntrustedTouchesTest,
8597 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8598 const sp<FakeWindowHandle>& w =
8599 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008600 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008601 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008602
8603 touch();
8604
8605 w->consumeMotionOutside();
8606}
8607
8608TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8609 const sp<FakeWindowHandle>& w =
8610 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008611 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008612 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008613
8614 touch();
8615
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008616 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008617}
8618
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008619TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008620 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008621 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8622 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008623 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008624
8625 touch();
8626
8627 mTouchWindow->consumeAnyMotionDown();
8628}
8629
8630TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8631 const sp<FakeWindowHandle>& w =
8632 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8633 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008634 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008635
8636 touch();
8637
8638 mTouchWindow->consumeAnyMotionDown();
8639}
8640
8641TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008642 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008643 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8644 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008645 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008646
8647 touch();
8648
8649 mTouchWindow->assertNoEvents();
8650}
8651
8652TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8653 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8654 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008655 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8656 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008657 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008658 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8659 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008660 mDispatcher->onWindowInfosChanged(
8661 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008662
8663 touch();
8664
8665 mTouchWindow->assertNoEvents();
8666}
8667
8668TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8669 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8670 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008671 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8672 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008673 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008674 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8675 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008676 mDispatcher->onWindowInfosChanged(
8677 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008678
8679 touch();
8680
8681 mTouchWindow->consumeAnyMotionDown();
8682}
8683
8684TEST_F(InputDispatcherUntrustedTouchesTest,
8685 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8686 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008687 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8688 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008689 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008690 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8691 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008692 mDispatcher->onWindowInfosChanged(
8693 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008694
8695 touch();
8696
8697 mTouchWindow->consumeAnyMotionDown();
8698}
8699
8700TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8701 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008702 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8703 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008704 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008705 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8706 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008707 mDispatcher->onWindowInfosChanged(
8708 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008709
8710 touch();
8711
8712 mTouchWindow->assertNoEvents();
8713}
8714
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008715TEST_F(InputDispatcherUntrustedTouchesTest,
8716 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8717 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008718 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8719 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008720 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008721 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8722 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008723 mDispatcher->onWindowInfosChanged(
8724 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008725
8726 touch();
8727
8728 mTouchWindow->assertNoEvents();
8729}
8730
8731TEST_F(InputDispatcherUntrustedTouchesTest,
8732 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8733 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008734 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8735 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008736 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008737 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8738 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008739 mDispatcher->onWindowInfosChanged(
8740 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008741
8742 touch();
8743
8744 mTouchWindow->consumeAnyMotionDown();
8745}
8746
8747TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8748 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008749 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8750 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008751 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008752
8753 touch();
8754
8755 mTouchWindow->consumeAnyMotionDown();
8756}
8757
8758TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8759 const sp<FakeWindowHandle>& w =
8760 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008761 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008762
8763 touch();
8764
8765 mTouchWindow->consumeAnyMotionDown();
8766}
8767
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008768TEST_F(InputDispatcherUntrustedTouchesTest,
8769 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8770 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8771 const sp<FakeWindowHandle>& w =
8772 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008773 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008774
8775 touch();
8776
8777 mTouchWindow->assertNoEvents();
8778}
8779
8780TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8781 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8782 const sp<FakeWindowHandle>& w =
8783 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008784 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008785
8786 touch();
8787
8788 mTouchWindow->consumeAnyMotionDown();
8789}
8790
8791TEST_F(InputDispatcherUntrustedTouchesTest,
8792 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8793 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8794 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008795 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8796 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008797 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008798
8799 touch();
8800
8801 mTouchWindow->consumeAnyMotionDown();
8802}
8803
8804TEST_F(InputDispatcherUntrustedTouchesTest,
8805 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8806 const sp<FakeWindowHandle>& w1 =
8807 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8808 OPACITY_BELOW_THRESHOLD);
8809 const sp<FakeWindowHandle>& w2 =
8810 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8811 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008812 mDispatcher->onWindowInfosChanged(
8813 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008814
8815 touch();
8816
8817 mTouchWindow->assertNoEvents();
8818}
8819
8820/**
8821 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8822 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8823 * (which alone would result in allowing touches) does not affect the blocking behavior.
8824 */
8825TEST_F(InputDispatcherUntrustedTouchesTest,
8826 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8827 const sp<FakeWindowHandle>& wB =
8828 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8829 OPACITY_BELOW_THRESHOLD);
8830 const sp<FakeWindowHandle>& wC =
8831 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8832 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008833 mDispatcher->onWindowInfosChanged(
8834 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00008835
8836 touch();
8837
8838 mTouchWindow->assertNoEvents();
8839}
8840
8841/**
8842 * This test is testing that a window from a different UID but with same application token doesn't
8843 * block the touch. Apps can share the application token for close UI collaboration for example.
8844 */
8845TEST_F(InputDispatcherUntrustedTouchesTest,
8846 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8847 const sp<FakeWindowHandle>& w =
8848 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8849 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008850 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008851
8852 touch();
8853
8854 mTouchWindow->consumeAnyMotionDown();
8855}
8856
arthurhungb89ccb02020-12-30 16:19:01 +08008857class InputDispatcherDragTests : public InputDispatcherTest {
8858protected:
8859 std::shared_ptr<FakeApplicationHandle> mApp;
8860 sp<FakeWindowHandle> mWindow;
8861 sp<FakeWindowHandle> mSecondWindow;
8862 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008863 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008864 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8865 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008866
8867 void SetUp() override {
8868 InputDispatcherTest::SetUp();
8869 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008870 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008871 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008872
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008873 mSecondWindow =
8874 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008875 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008876
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008877 mSpyWindow =
8878 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008879 mSpyWindow->setSpy(true);
8880 mSpyWindow->setTrustedOverlay(true);
8881 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8882
arthurhungb89ccb02020-12-30 16:19:01 +08008883 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008884 mDispatcher->onWindowInfosChanged(
8885 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
8886 {},
8887 0,
8888 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008889 }
8890
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008891 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8892 switch (fromSource) {
8893 case AINPUT_SOURCE_TOUCHSCREEN:
8894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008895 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008896 ADISPLAY_ID_DEFAULT, {50, 50}))
8897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8898 break;
8899 case AINPUT_SOURCE_STYLUS:
8900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008901 injectMotionEvent(*mDispatcher,
8902 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8903 AINPUT_SOURCE_STYLUS)
8904 .buttonState(
8905 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
8906 .pointer(PointerBuilder(0, ToolType::STYLUS)
8907 .x(50)
8908 .y(50))
8909 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008910 break;
8911 case AINPUT_SOURCE_MOUSE:
8912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008913 injectMotionEvent(*mDispatcher,
8914 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8915 AINPUT_SOURCE_MOUSE)
8916 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8917 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8918 ToolType::MOUSE)
8919 .x(50)
8920 .y(50))
8921 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008922 break;
8923 default:
8924 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8925 }
arthurhungb89ccb02020-12-30 16:19:01 +08008926
8927 // Window should receive motion event.
8928 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008929 // Spy window should also receive motion event
8930 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008931 }
8932
8933 // Start performing drag, we will create a drag window and transfer touch to it.
8934 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8935 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008936 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008937 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008938 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008939 }
arthurhungb89ccb02020-12-30 16:19:01 +08008940
8941 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008942 mDragWindow =
8943 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008944 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008945 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
8946 *mWindow->getInfo(), *mSecondWindow->getInfo()},
8947 {},
8948 0,
8949 0});
arthurhungb89ccb02020-12-30 16:19:01 +08008950
8951 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008952 bool transferred =
8953 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008954 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008955 if (transferred) {
8956 mWindow->consumeMotionCancel();
8957 mDragWindow->consumeMotionDown();
8958 }
8959 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008960 }
8961};
8962
8963TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008964 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008965
8966 // Move on window.
8967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008968 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008969 ADISPLAY_ID_DEFAULT, {50, 50}))
8970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8971 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8972 mWindow->consumeDragEvent(false, 50, 50);
8973 mSecondWindow->assertNoEvents();
8974
8975 // Move to another window.
8976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008977 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008978 ADISPLAY_ID_DEFAULT, {150, 50}))
8979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8980 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8981 mWindow->consumeDragEvent(true, 150, 50);
8982 mSecondWindow->consumeDragEvent(false, 50, 50);
8983
8984 // Move back to original window.
8985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008986 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08008987 ADISPLAY_ID_DEFAULT, {50, 50}))
8988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8989 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8990 mWindow->consumeDragEvent(false, 50, 50);
8991 mSecondWindow->consumeDragEvent(true, -50, 50);
8992
8993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008994 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8995 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08008996 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8997 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8998 mWindow->assertNoEvents();
8999 mSecondWindow->assertNoEvents();
9000}
9001
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009002TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009003 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009004
9005 // No cancel event after drag start
9006 mSpyWindow->assertNoEvents();
9007
9008 const MotionEvent secondFingerDownEvent =
9009 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9010 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009011 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9012 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009013 .build();
9014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009015 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009016 InputEventInjectionSync::WAIT_FOR_RESULT))
9017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9018
9019 // Receives cancel for first pointer after next pointer down
9020 mSpyWindow->consumeMotionCancel();
9021 mSpyWindow->consumeMotionDown();
9022
9023 mSpyWindow->assertNoEvents();
9024}
9025
arthurhungf452d0b2021-01-06 00:19:52 +08009026TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009027 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009028
9029 // Move on window.
9030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009031 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009032 ADISPLAY_ID_DEFAULT, {50, 50}))
9033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9034 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9035 mWindow->consumeDragEvent(false, 50, 50);
9036 mSecondWindow->assertNoEvents();
9037
9038 // Move to another window.
9039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009040 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009041 ADISPLAY_ID_DEFAULT, {150, 50}))
9042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9043 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9044 mWindow->consumeDragEvent(true, 150, 50);
9045 mSecondWindow->consumeDragEvent(false, 50, 50);
9046
9047 // drop to another window.
9048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009049 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009050 {150, 50}))
9051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9052 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009053 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009054 mWindow->assertNoEvents();
9055 mSecondWindow->assertNoEvents();
9056}
9057
arthurhung6d4bed92021-03-17 11:59:33 +08009058TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009059 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009060
9061 // Move on window and keep button pressed.
9062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009063 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009064 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9065 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009066 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009067 .build()))
9068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9069 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9070 mWindow->consumeDragEvent(false, 50, 50);
9071 mSecondWindow->assertNoEvents();
9072
9073 // Move to another window and release button, expect to drop item.
9074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009075 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009076 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9077 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009078 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009079 .build()))
9080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9081 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9082 mWindow->assertNoEvents();
9083 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009084 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009085
9086 // nothing to the window.
9087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009088 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009089 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9090 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009091 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009092 .build()))
9093 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9094 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9095 mWindow->assertNoEvents();
9096 mSecondWindow->assertNoEvents();
9097}
9098
Arthur Hung54745652022-04-20 07:17:41 +00009099TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009100 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009101
9102 // Set second window invisible.
9103 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009104 mDispatcher->onWindowInfosChanged(
9105 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009106
9107 // Move on window.
9108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009109 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009110 ADISPLAY_ID_DEFAULT, {50, 50}))
9111 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9112 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9113 mWindow->consumeDragEvent(false, 50, 50);
9114 mSecondWindow->assertNoEvents();
9115
9116 // Move to another window.
9117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009118 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009119 ADISPLAY_ID_DEFAULT, {150, 50}))
9120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9121 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9122 mWindow->consumeDragEvent(true, 150, 50);
9123 mSecondWindow->assertNoEvents();
9124
9125 // drop to another window.
9126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009127 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009128 {150, 50}))
9129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9130 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009131 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009132 mWindow->assertNoEvents();
9133 mSecondWindow->assertNoEvents();
9134}
9135
Arthur Hung54745652022-04-20 07:17:41 +00009136TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009137 // Ensure window could track pointerIds if it didn't support split touch.
9138 mWindow->setPreventSplitting(true);
9139
Arthur Hung54745652022-04-20 07:17:41 +00009140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009141 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009142 {50, 50}))
9143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9144 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9145
9146 const MotionEvent secondFingerDownEvent =
9147 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9148 .displayId(ADISPLAY_ID_DEFAULT)
9149 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009150 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9151 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009152 .build();
9153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009154 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009155 InputEventInjectionSync::WAIT_FOR_RESULT))
9156 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009157 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009158
9159 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009160 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009161}
9162
9163TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9164 // First down on second window.
9165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009166 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009167 {150, 50}))
9168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9169
9170 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9171
9172 // Second down on first window.
9173 const MotionEvent secondFingerDownEvent =
9174 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9175 .displayId(ADISPLAY_ID_DEFAULT)
9176 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009177 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9178 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009179 .build();
9180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009181 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009182 InputEventInjectionSync::WAIT_FOR_RESULT))
9183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9184 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9185
9186 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009187 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009188
9189 // Move on window.
9190 const MotionEvent secondFingerMoveEvent =
9191 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9192 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009193 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9194 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009195 .build();
9196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009197 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009198 InputEventInjectionSync::WAIT_FOR_RESULT));
9199 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9200 mWindow->consumeDragEvent(false, 50, 50);
9201 mSecondWindow->consumeMotionMove();
9202
9203 // Release the drag pointer should perform drop.
9204 const MotionEvent secondFingerUpEvent =
9205 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9206 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009207 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9208 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009209 .build();
9210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009211 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009212 InputEventInjectionSync::WAIT_FOR_RESULT));
9213 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009214 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00009215 mWindow->assertNoEvents();
9216 mSecondWindow->consumeMotionMove();
9217}
9218
Arthur Hung3915c1f2022-05-31 07:17:17 +00009219TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009220 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00009221
9222 // Update window of second display.
9223 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009224 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009225 mDispatcher->onWindowInfosChanged(
9226 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9227 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9228 {},
9229 0,
9230 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009231
9232 // Let second display has a touch state.
9233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009234 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009235 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9236 AINPUT_SOURCE_TOUCHSCREEN)
9237 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009238 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00009239 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009240 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00009241 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00009242 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009243 mDispatcher->onWindowInfosChanged(
9244 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
9245 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
9246 {},
9247 0,
9248 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +00009249
9250 // Move on window.
9251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009252 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009253 ADISPLAY_ID_DEFAULT, {50, 50}))
9254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9255 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9256 mWindow->consumeDragEvent(false, 50, 50);
9257 mSecondWindow->assertNoEvents();
9258
9259 // Move to another window.
9260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009261 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009262 ADISPLAY_ID_DEFAULT, {150, 50}))
9263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9264 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9265 mWindow->consumeDragEvent(true, 150, 50);
9266 mSecondWindow->consumeDragEvent(false, 50, 50);
9267
9268 // drop to another window.
9269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009270 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +00009271 {150, 50}))
9272 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9273 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009274 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00009275 mWindow->assertNoEvents();
9276 mSecondWindow->assertNoEvents();
9277}
9278
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009279TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
9280 startDrag(true, AINPUT_SOURCE_MOUSE);
9281 // Move on window.
9282 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009283 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009284 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9285 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009286 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009287 .x(50)
9288 .y(50))
9289 .build()))
9290 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9291 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9292 mWindow->consumeDragEvent(false, 50, 50);
9293 mSecondWindow->assertNoEvents();
9294
9295 // Move to another window.
9296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009297 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009298 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
9299 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009300 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009301 .x(150)
9302 .y(50))
9303 .build()))
9304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9305 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9306 mWindow->consumeDragEvent(true, 150, 50);
9307 mSecondWindow->consumeDragEvent(false, 50, 50);
9308
9309 // drop to another window.
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009311 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009312 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
9313 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009314 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009315 .x(150)
9316 .y(50))
9317 .build()))
9318 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9319 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009320 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009321 mWindow->assertNoEvents();
9322 mSecondWindow->assertNoEvents();
9323}
9324
Vishnu Nair062a8672021-09-03 16:07:44 -07009325class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
9326
9327TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
9328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009329 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9330 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009331 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009332 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9333 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009334 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009335 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009336 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009337
9338 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009339 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009340 window->assertNoEvents();
9341
Prabir Pradhan678438e2023-04-13 19:32:51 +00009342 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9343 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009344 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9345 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009346 window->assertNoEvents();
9347
9348 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009349 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009350 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009351
Prabir Pradhan678438e2023-04-13 19:32:51 +00009352 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009353 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9354
Prabir Pradhan678438e2023-04-13 19:32:51 +00009355 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9356 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009357 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9358 window->assertNoEvents();
9359}
9360
9361TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
9362 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9363 std::make_shared<FakeApplicationHandle>();
9364 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009365 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9366 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009367 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009368 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009369 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009371 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9372 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009373 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009374 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009375 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9376 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009377 mDispatcher->onWindowInfosChanged(
9378 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009379 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009380 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009381
9382 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009383 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009384 window->assertNoEvents();
9385
Prabir Pradhan678438e2023-04-13 19:32:51 +00009386 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9387 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009388 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9389 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009390 window->assertNoEvents();
9391
9392 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009393 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009394 mDispatcher->onWindowInfosChanged(
9395 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009396
Prabir Pradhan678438e2023-04-13 19:32:51 +00009397 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009398 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9399
Prabir Pradhan678438e2023-04-13 19:32:51 +00009400 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9401 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009402 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
9403 window->assertNoEvents();
9404}
9405
9406TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
9407 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
9408 std::make_shared<FakeApplicationHandle>();
9409 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009410 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
9411 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07009412 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009413 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009414 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07009415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009416 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
9417 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009418 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009419 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07009420 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9421 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009422 mDispatcher->onWindowInfosChanged(
9423 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009424 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009425 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07009426
9427 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00009428 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009429 window->assertNoEvents();
9430
Prabir Pradhan678438e2023-04-13 19:32:51 +00009431 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9432 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07009433 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
9434 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009435 window->assertNoEvents();
9436
9437 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009438 mDispatcher->onWindowInfosChanged(
9439 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -07009440
Prabir Pradhan678438e2023-04-13 19:32:51 +00009441 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009442 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
9443
Prabir Pradhan678438e2023-04-13 19:32:51 +00009444 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9445 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07009446 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9447 window->assertNoEvents();
9448}
9449
Antonio Kantekf16f2832021-09-28 04:39:20 +00009450class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
9451protected:
9452 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00009453 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009454 sp<FakeWindowHandle> mWindow;
9455 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00009456 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00009457
9458 void SetUp() override {
9459 InputDispatcherTest::SetUp();
9460
9461 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009462 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009463 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009464 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009465 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009466 mSecondWindow =
9467 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009468 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009469 mThirdWindow =
9470 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9471 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9472 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009473
9474 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009475 mDispatcher->onWindowInfosChanged(
9476 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
9477 {},
9478 0,
9479 0});
Antonio Kantek15beb512022-06-13 22:35:41 +00009480 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009481 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009482
Antonio Kantek15beb512022-06-13 22:35:41 +00009483 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009484 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009485 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009486 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9487 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009488 mThirdWindow->assertNoEvents();
9489 }
9490
9491 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9492 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009493 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009494 SECOND_DISPLAY_ID)) {
9495 mWindow->assertNoEvents();
9496 mSecondWindow->assertNoEvents();
9497 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009498 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009499 }
9500
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009501 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009502 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009503 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9504 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009505 mWindow->consumeTouchModeEvent(inTouchMode);
9506 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009507 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009508 }
9509};
9510
Antonio Kantek26defcf2022-02-08 01:12:27 +00009511TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009512 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009513 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9514 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009515 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009516}
9517
Antonio Kantek26defcf2022-02-08 01:12:27 +00009518TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9519 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009520 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009521 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009522 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009523 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009524 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009525 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009526 mWindow->assertNoEvents();
9527 mSecondWindow->assertNoEvents();
9528}
9529
9530TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9531 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009532 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009533 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009534 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009535 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009536 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009537}
9538
Antonio Kantekf16f2832021-09-28 04:39:20 +00009539TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009540 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009541 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9542 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009543 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009544 mWindow->assertNoEvents();
9545 mSecondWindow->assertNoEvents();
9546}
9547
Antonio Kantek15beb512022-06-13 22:35:41 +00009548TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9549 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9550 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9551 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009552 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009553 mWindow->assertNoEvents();
9554 mSecondWindow->assertNoEvents();
9555 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9556}
9557
Antonio Kantek48710e42022-03-24 14:19:30 -07009558TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9559 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9561 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -07009562 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9563 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9564
9565 // Then remove focus.
9566 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009567 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -07009568
9569 // Assert that caller can switch touch mode by owning one of the last interacted window.
9570 const WindowInfo& windowInfo = *mWindow->getInfo();
9571 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9572 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009573 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009574}
9575
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009576class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9577public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009578 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009579 std::shared_ptr<FakeApplicationHandle> application =
9580 std::make_shared<FakeApplicationHandle>();
9581 std::string name = "Fake Spy ";
9582 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009583 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9584 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009585 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009586 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009587 return spy;
9588 }
9589
9590 sp<FakeWindowHandle> createForeground() {
9591 std::shared_ptr<FakeApplicationHandle> application =
9592 std::make_shared<FakeApplicationHandle>();
9593 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009594 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9595 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009596 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009597 return window;
9598 }
9599
9600private:
9601 int mSpyCount{0};
9602};
9603
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009604using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009605/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009606 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9607 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009608TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07009609 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009610 ScopedSilentDeath _silentDeath;
9611
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009612 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009613 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009614 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009615 ".* not a trusted overlay");
9616}
9617
9618/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009619 * Input injection into a display with a spy window but no foreground windows should succeed.
9620 */
9621TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009622 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009623 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009624
9625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009626 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009627 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9628 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9629}
9630
9631/**
9632 * Verify the order in which different input windows receive events. The touched foreground window
9633 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9634 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9635 * receive events before ones belows it.
9636 *
9637 * Here, we set up a scenario with four windows in the following Z order from the top:
9638 * spy1, spy2, window, spy3.
9639 * We then inject an event and verify that the foreground "window" receives it first, followed by
9640 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9641 * window.
9642 */
9643TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9644 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009645 auto spy1 = createSpy();
9646 auto spy2 = createSpy();
9647 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009648 mDispatcher->onWindowInfosChanged(
9649 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009650 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9651 const size_t numChannels = channels.size();
9652
Michael Wright8e9a8562022-02-09 13:44:29 +00009653 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009654 if (!epollFd.ok()) {
9655 FAIL() << "Failed to create epoll fd";
9656 }
9657
9658 for (size_t i = 0; i < numChannels; i++) {
9659 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9660 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9661 FAIL() << "Failed to add fd to epoll";
9662 }
9663 }
9664
9665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009666 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9668
9669 std::vector<size_t> eventOrder;
9670 std::vector<struct epoll_event> events(numChannels);
9671 for (;;) {
9672 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9673 (100ms).count());
9674 if (nFds < 0) {
9675 FAIL() << "Failed to call epoll_wait";
9676 }
9677 if (nFds == 0) {
9678 break; // epoll_wait timed out
9679 }
9680 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009681 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009682 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009683 channels[i]->consumeMotionDown();
9684 }
9685 }
9686
9687 // Verify the order in which the events were received.
9688 EXPECT_EQ(3u, eventOrder.size());
9689 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9690 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9691 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9692}
9693
9694/**
9695 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9696 */
9697TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9698 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009699 auto spy = createSpy();
9700 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009701 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009702
9703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009704 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9706 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9707 spy->assertNoEvents();
9708}
9709
9710/**
9711 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9712 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9713 * to the window.
9714 */
9715TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9716 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009717 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009718 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009719 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009720
9721 // Inject an event outside the spy window's touchable region.
9722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009723 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009724 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9725 window->consumeMotionDown();
9726 spy->assertNoEvents();
9727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009728 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9730 window->consumeMotionUp();
9731 spy->assertNoEvents();
9732
9733 // Inject an event inside the spy window's touchable region.
9734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009735 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009736 {5, 10}))
9737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9738 window->consumeMotionDown();
9739 spy->consumeMotionDown();
9740}
9741
9742/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009743 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009744 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009745 */
9746TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9747 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009748 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009749 auto spy = createSpy();
9750 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009751 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009752 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009753 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009754
9755 // Inject an event outside the spy window's frame and touchable region.
9756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009757 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009758 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9760 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009761 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009762}
9763
9764/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009765 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9766 * pointers that are down within its bounds.
9767 */
9768TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9769 auto windowLeft = createForeground();
9770 windowLeft->setFrame({0, 0, 100, 200});
9771 auto windowRight = createForeground();
9772 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009773 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009774 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009775 mDispatcher->onWindowInfosChanged(
9776 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009777
9778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009779 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009780 {50, 50}))
9781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9782 windowLeft->consumeMotionDown();
9783 spy->consumeMotionDown();
9784
9785 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009786 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009787 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009788 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9789 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009790 .build();
9791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009792 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009793 InputEventInjectionSync::WAIT_FOR_RESULT))
9794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9795 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009796 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009797}
9798
9799/**
9800 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9801 * the spy should receive the second pointer with ACTION_DOWN.
9802 */
9803TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9804 auto window = createForeground();
9805 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009806 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009807 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009808 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009809
9810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009811 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009812 {50, 50}))
9813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9814 window->consumeMotionDown();
9815 spyRight->assertNoEvents();
9816
9817 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009818 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009819 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009820 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9821 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009822 .build();
9823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009824 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009825 InputEventInjectionSync::WAIT_FOR_RESULT))
9826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009827 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009828 spyRight->consumeMotionDown();
9829}
9830
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009831/**
9832 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9833 * windows should be allowed to control split touch.
9834 */
9835TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009836 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009837 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009838 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009839 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009840
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009841 auto window = createForeground();
9842 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009843
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009844 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009845
9846 // First finger down, no window touched.
9847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009848 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009849 {100, 200}))
9850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9851 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9852 window->assertNoEvents();
9853
9854 // Second finger down on window, the window should receive touch down.
9855 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009856 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009857 .displayId(ADISPLAY_ID_DEFAULT)
9858 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009859 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9860 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009861 .build();
9862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009863 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009864 InputEventInjectionSync::WAIT_FOR_RESULT))
9865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9866
9867 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009868 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009869}
9870
9871/**
9872 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9873 * do not receive key events.
9874 */
9875TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009876 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009877 spy->setFocusable(false);
9878
9879 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009880 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009881 setFocusedWindow(window);
9882 window->consumeFocusEvent(true);
9883
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009885 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9886 window->consumeKeyDown(ADISPLAY_ID_NONE);
9887
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009889 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9890 window->consumeKeyUp(ADISPLAY_ID_NONE);
9891
9892 spy->assertNoEvents();
9893}
9894
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009895using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9896
9897/**
9898 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9899 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9900 */
9901TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9902 auto window = createForeground();
9903 auto spy1 = createSpy();
9904 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009905 mDispatcher->onWindowInfosChanged(
9906 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009907
9908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009909 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9911 window->consumeMotionDown();
9912 spy1->consumeMotionDown();
9913 spy2->consumeMotionDown();
9914
9915 // Pilfer pointers from the second spy window.
9916 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9917 spy2->assertNoEvents();
9918 spy1->consumeMotionCancel();
9919 window->consumeMotionCancel();
9920
9921 // The rest of the gesture should only be sent to the second spy window.
9922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009923 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009924 ADISPLAY_ID_DEFAULT))
9925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9926 spy2->consumeMotionMove();
9927 spy1->assertNoEvents();
9928 window->assertNoEvents();
9929}
9930
9931/**
9932 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9933 * in the middle of the gesture.
9934 */
9935TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9936 auto window = createForeground();
9937 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009938 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009939
9940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009941 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9943 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9944 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9945
9946 window->releaseChannel();
9947
9948 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9949
9950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009951 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009952 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9953 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9954}
9955
9956/**
9957 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9958 * the spy, but not to any other windows.
9959 */
9960TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9961 auto spy = createSpy();
9962 auto window = createForeground();
9963
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009964 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009965
9966 // First finger down on the window and the spy.
9967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009968 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009969 {100, 200}))
9970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9971 spy->consumeMotionDown();
9972 window->consumeMotionDown();
9973
9974 // Spy window pilfers the pointers.
9975 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9976 window->consumeMotionCancel();
9977
9978 // Second finger down on the window and spy, but the window should not receive the pointer down.
9979 const MotionEvent secondFingerDownEvent =
9980 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9981 .displayId(ADISPLAY_ID_DEFAULT)
9982 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009983 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9984 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009985 .build();
9986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009987 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009988 InputEventInjectionSync::WAIT_FOR_RESULT))
9989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9990
Harry Cutts33476232023-01-30 19:57:29 +00009991 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009992
9993 // Third finger goes down outside all windows, so injection should fail.
9994 const MotionEvent thirdFingerDownEvent =
9995 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9996 .displayId(ADISPLAY_ID_DEFAULT)
9997 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009998 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9999 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10000 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010001 .build();
10002 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010003 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010004 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010005 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010006
10007 spy->assertNoEvents();
10008 window->assertNoEvents();
10009}
10010
10011/**
10012 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10013 */
10014TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10015 auto spy = createSpy();
10016 spy->setFrame(Rect(0, 0, 100, 100));
10017 auto window = createForeground();
10018 window->setFrame(Rect(0, 0, 200, 200));
10019
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010020 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010021
10022 // First finger down on the window only
10023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010024 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010025 {150, 150}))
10026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10027 window->consumeMotionDown();
10028
10029 // Second finger down on the spy and window
10030 const MotionEvent secondFingerDownEvent =
10031 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10032 .displayId(ADISPLAY_ID_DEFAULT)
10033 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010034 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10035 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010036 .build();
10037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010038 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010039 InputEventInjectionSync::WAIT_FOR_RESULT))
10040 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10041 spy->consumeMotionDown();
10042 window->consumeMotionPointerDown(1);
10043
10044 // Third finger down on the spy and window
10045 const MotionEvent thirdFingerDownEvent =
10046 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10047 .displayId(ADISPLAY_ID_DEFAULT)
10048 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010049 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10050 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10051 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010052 .build();
10053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010054 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010055 InputEventInjectionSync::WAIT_FOR_RESULT))
10056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10057 spy->consumeMotionPointerDown(1);
10058 window->consumeMotionPointerDown(2);
10059
10060 // Spy window pilfers the pointers.
10061 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010062 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10063 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010064
10065 spy->assertNoEvents();
10066 window->assertNoEvents();
10067}
10068
10069/**
10070 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10071 * other windows should be canceled. If this results in the cancellation of all pointers for some
10072 * window, then that window should receive ACTION_CANCEL.
10073 */
10074TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10075 auto spy = createSpy();
10076 spy->setFrame(Rect(0, 0, 100, 100));
10077 auto window = createForeground();
10078 window->setFrame(Rect(0, 0, 200, 200));
10079
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010080 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010081
10082 // First finger down on both spy and window
10083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010084 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010085 {10, 10}))
10086 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10087 window->consumeMotionDown();
10088 spy->consumeMotionDown();
10089
10090 // Second finger down on the spy and window
10091 const MotionEvent secondFingerDownEvent =
10092 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10093 .displayId(ADISPLAY_ID_DEFAULT)
10094 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010095 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10096 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010097 .build();
10098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010099 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010100 InputEventInjectionSync::WAIT_FOR_RESULT))
10101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10102 spy->consumeMotionPointerDown(1);
10103 window->consumeMotionPointerDown(1);
10104
10105 // Spy window pilfers the pointers.
10106 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10107 window->consumeMotionCancel();
10108
10109 spy->assertNoEvents();
10110 window->assertNoEvents();
10111}
10112
10113/**
10114 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
10115 * be sent to other windows
10116 */
10117TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
10118 auto spy = createSpy();
10119 spy->setFrame(Rect(0, 0, 100, 100));
10120 auto window = createForeground();
10121 window->setFrame(Rect(0, 0, 200, 200));
10122
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010123 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010124
10125 // First finger down on both window and spy
10126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010127 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010128 {10, 10}))
10129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10130 window->consumeMotionDown();
10131 spy->consumeMotionDown();
10132
10133 // Spy window pilfers the pointers.
10134 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10135 window->consumeMotionCancel();
10136
10137 // Second finger down on the window only
10138 const MotionEvent secondFingerDownEvent =
10139 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10140 .displayId(ADISPLAY_ID_DEFAULT)
10141 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010142 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10143 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010144 .build();
10145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010146 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010147 InputEventInjectionSync::WAIT_FOR_RESULT))
10148 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10149 window->consumeMotionDown();
10150 window->assertNoEvents();
10151
10152 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
10153 spy->consumeMotionMove();
10154 spy->assertNoEvents();
10155}
10156
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010157/**
10158 * A window on the left and a window on the right. Also, a spy window that's above all of the
10159 * windows, and spanning both left and right windows.
10160 * Send simultaneous motion streams from two different devices, one to the left window, and another
10161 * to the right window.
10162 * Pilfer from spy window.
10163 * Check that the pilfering only affects the pointers that are actually being received by the spy.
10164 */
10165TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
10166 sp<FakeWindowHandle> spy = createSpy();
10167 spy->setFrame(Rect(0, 0, 200, 200));
10168 sp<FakeWindowHandle> leftWindow = createForeground();
10169 leftWindow->setFrame(Rect(0, 0, 100, 100));
10170
10171 sp<FakeWindowHandle> rightWindow = createForeground();
10172 rightWindow->setFrame(Rect(100, 0, 200, 100));
10173
10174 constexpr int32_t stylusDeviceId = 1;
10175 constexpr int32_t touchDeviceId = 2;
10176
10177 mDispatcher->onWindowInfosChanged(
10178 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
10179
10180 // Stylus down on left window and spy
10181 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
10182 .deviceId(stylusDeviceId)
10183 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
10184 .build());
10185 leftWindow->consumeMotionEvent(
10186 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10187 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
10188
10189 // Finger down on right window and spy - but spy already has stylus
10190 mDispatcher->notifyMotion(
10191 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10192 .deviceId(touchDeviceId)
10193 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
10194 .build());
10195 rightWindow->consumeMotionEvent(
10196 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10197 leftWindow->consumeMotionEvent(
10198 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10199 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
10200 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
10201
10202 // Act: pilfer from spy. Spy is currently receiving touch events.
10203 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10204 rightWindow->consumeMotionEvent(
10205 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
10206
10207 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
10208 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10209 .deviceId(stylusDeviceId)
10210 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
10211 .build());
10212 mDispatcher->notifyMotion(
10213 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10214 .deviceId(touchDeviceId)
10215 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
10216 .build());
10217 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
10218
10219 spy->assertNoEvents();
10220 leftWindow->assertNoEvents();
10221 rightWindow->assertNoEvents();
10222}
10223
Prabir Pradhand65552b2021-10-07 11:23:50 -070010224class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
10225public:
10226 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
10227 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10228 std::make_shared<FakeApplicationHandle>();
10229 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010230 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10231 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010232 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010233 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010234 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010235 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010236 overlay->setTrustedOverlay(true);
10237
10238 std::shared_ptr<FakeApplicationHandle> application =
10239 std::make_shared<FakeApplicationHandle>();
10240 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010241 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
10242 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010243 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010244 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010245
10246 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010247 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010248 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010249 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010250 return {std::move(overlay), std::move(window)};
10251 }
10252
10253 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010254 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070010255 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010256 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070010257 }
10258
10259 void sendStylusEvent(int32_t action) {
10260 NotifyMotionArgs motionArgs =
10261 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
10262 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010263 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000010264 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070010265 }
10266};
10267
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010268using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
10269
10270TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070010271 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010272 ScopedSilentDeath _silentDeath;
10273
Prabir Pradhand65552b2021-10-07 11:23:50 -070010274 auto [overlay, window] = setupStylusOverlayScenario();
10275 overlay->setTrustedOverlay(false);
10276 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010277 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
10278 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070010279 ".* not a trusted overlay");
10280}
10281
10282TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
10283 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010284 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010285
10286 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10287 overlay->consumeMotionDown();
10288 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10289 overlay->consumeMotionUp();
10290
10291 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10292 window->consumeMotionDown();
10293 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10294 window->consumeMotionUp();
10295
10296 overlay->assertNoEvents();
10297 window->assertNoEvents();
10298}
10299
10300TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
10301 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010302 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010303 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070010304
10305 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10306 overlay->consumeMotionDown();
10307 window->consumeMotionDown();
10308 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10309 overlay->consumeMotionUp();
10310 window->consumeMotionUp();
10311
10312 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
10313 window->consumeMotionDown();
10314 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
10315 window->consumeMotionUp();
10316
10317 overlay->assertNoEvents();
10318 window->assertNoEvents();
10319}
10320
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010321/**
10322 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
10323 * The scenario is as follows:
10324 * - The stylus interceptor overlay is configured as a spy window.
10325 * - The stylus interceptor spy receives the start of a new stylus gesture.
10326 * - It pilfers pointers and then configures itself to no longer be a spy.
10327 * - The stylus interceptor continues to receive the rest of the gesture.
10328 */
10329TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
10330 auto [overlay, window] = setupStylusOverlayScenario();
10331 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010332 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010333
10334 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
10335 overlay->consumeMotionDown();
10336 window->consumeMotionDown();
10337
10338 // The interceptor pilfers the pointers.
10339 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
10340 window->consumeMotionCancel();
10341
10342 // The interceptor configures itself so that it is no longer a spy.
10343 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010344 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000010345
10346 // It continues to receive the rest of the stylus gesture.
10347 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
10348 overlay->consumeMotionMove();
10349 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
10350 overlay->consumeMotionUp();
10351
10352 window->assertNoEvents();
10353}
10354
Prabir Pradhan5735a322022-04-11 17:23:34 +000010355struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010356 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010357 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000010358 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
10359 std::unique_ptr<InputDispatcher>& mDispatcher;
10360
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010361 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000010362 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
10363
10364 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010365 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010366 ADISPLAY_ID_DEFAULT, {100, 200},
10367 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10368 AMOTION_EVENT_INVALID_CURSOR_POSITION},
10369 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
10370 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
10371 }
10372
10373 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010374 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010375 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000010376 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000010377 mPolicyFlags);
10378 }
10379
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010380 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000010381 std::shared_ptr<FakeApplicationHandle> overlayApplication =
10382 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010383 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
10384 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000010385 window->setOwnerInfo(mPid, mUid);
10386 return window;
10387 }
10388};
10389
10390using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
10391
10392TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010393 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010394 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010395 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010396
10397 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10398 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10399 window->consumeMotionDown();
10400
10401 setFocusedWindow(window);
10402 window->consumeFocusEvent(true);
10403
10404 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10405 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10406 window->consumeKeyDown(ADISPLAY_ID_NONE);
10407}
10408
10409TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010410 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010411 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010413
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010414 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010415 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10416 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10417
10418 setFocusedWindow(window);
10419 window->consumeFocusEvent(true);
10420
10421 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
10422 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
10423 window->assertNoEvents();
10424}
10425
10426TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010427 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010428 auto window = owner.createWindow("Owned window");
10429 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010430 spy->setSpy(true);
10431 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010432 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010433
10434 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10435 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10436 spy->consumeMotionDown();
10437 window->consumeMotionDown();
10438}
10439
10440TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010441 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010442 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010443
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010444 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010445 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010446 randosSpy->setSpy(true);
10447 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010448 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010449
10450 // The event is targeted at owner's window, so injection should succeed, but the spy should
10451 // not receive the event.
10452 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10453 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10454 randosSpy->assertNoEvents();
10455 window->consumeMotionDown();
10456}
10457
10458TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010459 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010460 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010461
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010462 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010463 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010464 randosSpy->setSpy(true);
10465 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010466 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010467
10468 // A user that has injection permission can inject into any window.
10469 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010470 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000010471 ADISPLAY_ID_DEFAULT));
10472 randosSpy->consumeMotionDown();
10473 window->consumeMotionDown();
10474
10475 setFocusedWindow(randosSpy);
10476 randosSpy->consumeFocusEvent(true);
10477
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010478 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000010479 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
10480 window->assertNoEvents();
10481}
10482
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010483TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010484 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010485 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010486
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010487 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070010488 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000010489 randosWindow->setFrame(Rect{-10, -10, -5, -5});
10490 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010491 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000010492
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010493 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010494 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
10495 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
10496 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070010497 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000010498}
10499
Garfield Tane84e6f92019-08-29 17:28:41 -070010500} // namespace android::inputdispatcher