blob: 8be1b3ba00dc2a7428f77929f08a020f21859aaf [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 Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800159
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000161 FakeInputDispatcherPolicy() = default;
162 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800163
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800164 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700166 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& keyEvent = static_cast<const KeyEvent&>(event);
170 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(keyEvent.getAction(), args.action);
172 });
Jackal Guof9696682018-10-05 12:23:23 +0800173 }
174
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
176 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700177 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700178 EXPECT_EQ(event.getDisplayId(), args.displayId);
179
180 const auto& motionEvent = static_cast<const MotionEvent&>(event);
181 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
182 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000183 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
186 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700190 void assertFilterInputEventWasNotCalled() {
191 std::scoped_lock lock(mLock);
192 ASSERT_EQ(nullptr, mFilteredEvent);
193 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700196 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 ASSERT_TRUE(mConfigurationChangedTime)
198 << "Timed out waiting for configuration changed call";
199 ASSERT_EQ(*mConfigurationChangedTime, when);
200 mConfigurationChangedTime = std::nullopt;
201 }
202
203 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800206 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
208 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
209 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
210 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
211 mLastNotifySwitch = std::nullopt;
212 }
213
chaviwfd6d3512019-03-25 13:23:49 -0700214 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800216 ASSERT_EQ(touchedToken, mOnPointerDownToken);
217 mOnPointerDownToken.clear();
218 }
219
220 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mOnPointerDownToken == nullptr)
223 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700224 }
225
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700226 // This function must be called soon after the expected ANR timer starts,
227 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700229 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 std::unique_lock lock(mLock);
232 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800234 ASSERT_NO_FATAL_FAILURE(
235 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500236 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
238
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000239 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800240 const sp<WindowInfoHandle>& window) {
241 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
242 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
243 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 }
245
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
247 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000248 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 std::unique_lock lock(mLock);
250 android::base::ScopedLockAssertion assumeLocked(mLock);
251 AnrResult result;
252 ASSERT_NO_FATAL_FAILURE(result =
253 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000254 ASSERT_EQ(expectedToken, result.token);
255 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500256 }
257
Prabir Pradhanedd96402022-02-15 01:46:16 -0800258 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 std::unique_lock lock(mLock);
261 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
263 const auto& [token, _] = result;
264 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000265 }
266
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 std::unique_lock lock(mLock);
270 android::base::ScopedLockAssertion assumeLocked(mLock);
271 AnrResult result;
272 ASSERT_NO_FATAL_FAILURE(
273 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000274 ASSERT_EQ(expectedToken, result.token);
275 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 }
277
278 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 sp<IBinder> getResponsiveWindowToken() {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
283 const auto& [token, _] = result;
284 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
287 void assertNotifyAnrWasNotCalled() {
288 std::scoped_lock lock(mLock);
289 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_TRUE(mAnrWindows.empty());
291 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 << "ANR was not called, but please also consume the 'connection is responsive' "
293 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700294 }
295
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::unique_lock lock(mLock);
298 base::ScopedLockAssertion assumeLocked(mLock);
299
300 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
301 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 enabled;
304 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
306 << ") to be called.";
307 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 auto request = *mPointerCaptureRequest;
310 mPointerCaptureRequest.reset();
311 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
313
314 void assertSetPointerCaptureNotCalled() {
315 std::unique_lock lock(mLock);
316 base::ScopedLockAssertion assumeLocked(mLock);
317
318 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
325
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700326 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
327 const sp<IBinder>& targetToken) {
328 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800329 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800331 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800332 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800333 }
334
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800335 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338 std::optional<sp<IBinder>> receivedToken =
339 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
340 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000341 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800342 ASSERT_EQ(token, *receivedToken);
343 }
344
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800345 /**
346 * Set policy timeout. A value of zero means next key will not be intercepted.
347 */
348 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
349 mInterceptKeyTimeout = timeout;
350 }
351
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700352 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
353
Josep del Riob3981622023-04-18 15:49:45 +0000354 void assertUserActivityPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
357 }
358
359 void assertUserActivityNotPoked() {
360 std::scoped_lock lock(mLock);
361 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
362 }
363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000364 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000365 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
366 }
367
368 void assertNotifyDeviceInteractionWasNotCalled() {
369 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
370 }
371
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000372 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
373 std::scoped_lock lock(mLock);
374 mUnhandledKeyHandler = handler;
375 }
376
377 void assertUnhandledKeyReported(int32_t keycode) {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380 std::optional<int32_t> unhandledKeycode =
381 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
382 mNotifyUnhandledKey);
383 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
384 ASSERT_EQ(unhandledKeycode, keycode);
385 }
386
387 void assertUnhandledKeyNotReported() {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<int32_t> unhandledKeycode =
391 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
392 mNotifyUnhandledKey);
393 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
394 }
395
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::mutex mLock;
398 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
399 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
400 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
401 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800402
Prabir Pradhan99987712020-11-10 18:43:05 -0800403 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000404
405 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800406
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700407 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700408 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800409 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
410 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800412 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
413 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700414
arthurhungf452d0b2021-01-06 00:19:52 +0800415 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800416 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000417 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800418
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800419 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
420
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700421 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000425 std::condition_variable mNotifyUnhandledKey;
426 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
427 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 return std::nullopt;
472 }
473 T item = storage.front();
474 storage.pop();
475 return std::make_optional(item);
476 }
477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800480 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 }
482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000483 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 ASSERT_TRUE(pid.has_value());
487 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000492 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 mNotifyAnr.notify_all();
497 }
498
499 void notifyNoFocusedWindowAnr(
500 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
501 std::scoped_lock lock(mLock);
502 mAnrApplications.push(applicationHandle);
503 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800506 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
507 std::scoped_lock lock(mLock);
508 mBrokenInputChannels.push(connectionToken);
509 mNotifyInputChannelBroken.notify_all();
510 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700513
Chris Yef59a2f42020-10-16 12:55:26 -0700514 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
515 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
516 const std::vector<float>& values) override {}
517
518 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
519 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000520
Chris Yefb552902021-02-03 17:18:37 -0800521 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
522
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700524 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700526 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
528 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800529 break;
530 }
531
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700532 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
534 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800535 break;
536 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700537 default: {
538 ADD_FAILURE() << "Should only filter keys or motions";
539 break;
540 }
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 return true;
543 }
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
546 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800547 // Clear intercept state when we handled the event.
548 mInterceptKeyTimeout = 0ms;
549 }
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800552 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
556 // Clear intercept state so we could dispatch the event in next wake.
557 mInterceptKeyTimeout = 0ms;
558 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 }
560
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000563 std::scoped_lock lock(mLock);
564 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
565 mNotifyUnhandledKey.notify_all();
566 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000575 mLastNotifySwitch =
576 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577 }
578
Josep del Riob3981622023-04-18 15:49:45 +0000579 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
580 std::scoped_lock lock(mLock);
581 mPokedUserActivity = true;
582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700584 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
585 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
586 }
587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700590 mOnPointerDownToken = newToken;
591 }
592
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000593 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800594 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000595 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800596 mPointerCaptureChangedCondition.notify_all();
597 }
598
arthurhungf452d0b2021-01-06 00:19:52 +0800599 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
600 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800601 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800602 mDropTargetWindowToken = token;
603 }
604
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000605 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000606 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000607 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
608 }
609
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700610 void assertFilterInputEventWasCalledInternal(
611 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700612 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800613 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700614 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800615 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800616 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700618} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620// --- InputDispatcherTest ---
621
622class InputDispatcherTest : public testing::Test {
623protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000624 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700625 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000627 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000628 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700629 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
630
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000632 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000636 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700637 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700641
642 /**
643 * Used for debugging when writing the test
644 */
645 void dumpDispatcherState() {
646 std::string dump;
647 mDispatcher->dump(dump);
648 std::stringstream ss(dump);
649 std::string to;
650
651 while (std::getline(ss, to, '\n')) {
652 ALOGE("%s", to.c_str());
653 }
654 }
Vishnu Nair958da932020-08-21 17:12:37 -0700655
Chavi Weingarten847e8512023-03-29 00:26:09 +0000656 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700657 FocusRequest request;
658 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000659 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700660 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
661 request.displayId = window->getInfo()->displayId;
662 mDispatcher->setFocusedWindow(request);
663 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664};
665
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
667 KeyEvent event;
668
669 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
671 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000672 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600673 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800674 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000675 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000676 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677 << "Should reject key events with undefined action.";
678
679 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000684 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000685 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686 << "Should reject key events with ACTION_MULTIPLE.";
687}
688
689TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
690 MotionEvent event;
691 PointerProperties pointerProperties[MAX_POINTERS + 1];
692 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800693 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 pointerProperties[i].clear();
695 pointerProperties[i].id = i;
696 pointerCoords[i].clear();
697 }
698
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800699 // Some constants commonly used below
700 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
701 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
702 constexpr int32_t metaState = AMETA_NONE;
703 constexpr MotionClassification classification = MotionClassification::NONE;
704
chaviw9eaa22c2020-07-01 16:21:27 -0700705 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000708 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000712 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with undefined action.";
717
718 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800720 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000724 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too large.";
729
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 AMOTION_EVENT_ACTION_POINTER_DOWN |
732 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700733 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000736 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too small.";
741
742 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800744 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
745 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
747 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000748 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too large.";
753
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700755 AMOTION_EVENT_ACTION_POINTER_UP |
756 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700757 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000760 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too small.";
765
766 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
768 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700769 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
771 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000772 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with 0 pointers.";
777
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000783 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with more than MAX_POINTERS pointers.";
788
789 // Rejects motion events with invalid pointer ids.
790 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids less than 0.";
801
802 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
813
814 // Rejects motion events with duplicate pointer ids.
815 pointerProperties[0].id = 1;
816 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with duplicate pointer ids.";
827}
828
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
830
831TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
832 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000833 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800834 ASSERT_TRUE(mDispatcher->waitForIdle());
835
836 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
837}
838
839TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000840 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
841 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000842 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000843 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800844
845 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
846 args.policyFlags |= POLICY_FLAG_TRUSTED;
847 mFakePolicy->assertNotifySwitchWasCalled(args);
848}
849
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700850namespace {
851
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700852static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700853// Default input dispatching timeout if there is no focused application or paused window
854// from which to determine an appropriate dispatching timeout.
855static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
856 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
857 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800858
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800859class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800860public:
Garfield Tan15601662020-09-22 15:32:38 -0700861 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700862 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800863
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000864 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700866 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867 if (!consumeSeq) {
868 return nullptr;
869 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000870 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 return event;
872 }
873
874 /**
875 * Receive an event without acknowledging it.
876 * Return the sequence number that could later be used to send finished signal.
877 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700878 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
879 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 uint32_t consumeSeq;
881 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800882
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 std::chrono::time_point start = std::chrono::steady_clock::now();
884 status_t status = WOULD_BLOCK;
885 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700886 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
887 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700889 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 break;
891 }
892 }
893
894 if (status == WOULD_BLOCK) {
895 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800897 }
898
899 if (status != OK) {
900 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700901 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 }
903 if (event == nullptr) {
904 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800906 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700907 if (outEvent != nullptr) {
908 *outEvent = event;
909 }
910 return consumeSeq;
911 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800912
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913 /**
914 * To be used together with "receiveEvent" to complete the consumption of an event.
915 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000916 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700917 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700918 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800919 }
920
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000921 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700922 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000923 ASSERT_EQ(OK, status);
924 }
925
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700926 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000927 std::optional<int32_t> expectedDisplayId,
928 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700929 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
931 ASSERT_NE(nullptr, event) << mName.c_str()
932 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800933 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700934 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
935 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800936
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000937 if (expectedDisplayId.has_value()) {
938 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
939 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800940
Tiger Huang8664f8c2018-10-11 19:14:35 +0800941 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800943 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700944 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 if (expectedFlags.has_value()) {
946 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
947 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800948 break;
949 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700950 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800951 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700952 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000953 if (expectedFlags.has_value()) {
954 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
955 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800956 break;
957 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100959 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
960 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700961 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800962 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000965 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
966 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700967 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800968 FAIL() << "Use 'consumeDragEvent' for DRAG events";
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800971 }
972
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800973 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700974 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800975
976 if (event == nullptr) {
977 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
978 return nullptr;
979 }
980
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 if (event->getType() != InputEventType::MOTION) {
982 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800983 return nullptr;
984 }
985 return static_cast<MotionEvent*>(event);
986 }
987
988 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
989 MotionEvent* motionEvent = consumeMotion();
990 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
991 ASSERT_THAT(*motionEvent, matcher);
992 }
993
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700995 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100996 ASSERT_NE(nullptr, event) << mName.c_str()
997 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 ASSERT_EQ(InputEventType::FOCUS, event->getType())
999 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001000
1001 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1002 << mName.c_str() << ": event displayId should always be NONE.";
1003
1004 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1005 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001006 }
1007
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001009 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001010 ASSERT_NE(nullptr, event) << mName.c_str()
1011 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1013 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001014
1015 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1016 << mName.c_str() << ": event displayId should always be NONE.";
1017
1018 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1019 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1020 }
1021
arthurhungb89ccb02020-12-30 16:19:01 +08001022 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001023 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001024 ASSERT_NE(nullptr, event) << mName.c_str()
1025 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001026 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001027
1028 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1029 << mName.c_str() << ": event displayId should always be NONE.";
1030
1031 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1032 EXPECT_EQ(isExiting, dragEvent.isExiting());
1033 EXPECT_EQ(x, dragEvent.getX());
1034 EXPECT_EQ(y, dragEvent.getY());
1035 }
1036
Antonio Kantekf16f2832021-09-28 04:39:20 +00001037 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001038 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001039 ASSERT_NE(nullptr, event) << mName.c_str()
1040 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001041 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1042 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001043
1044 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1047 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1048 }
1049
chaviwd1c23182019-12-20 18:44:56 -08001050 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001051 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 if (event == nullptr) {
1053 return;
1054 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001056 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001057 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001060 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1063 ADD_FAILURE() << "Received focus event, hasFocus = "
1064 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001066 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1067 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1068 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1071 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1072 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 }
1074 FAIL() << mName.c_str()
1075 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001076 }
1077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001081
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001082private:
1083 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001084 PreallocatedInputEventFactory mEventFactory;
1085
1086 std::string mName;
1087};
1088
chaviw3277faf2021-05-19 16:45:23 -05001089class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001090public:
1091 static const int32_t WIDTH = 600;
1092 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001093
Chris Yea209fde2020-07-22 13:54:51 -07001094 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001095 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001096 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001098 sp<IBinder> token;
1099 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001100 base::Result<std::unique_ptr<InputChannel>> channel =
1101 dispatcher->createInputChannel(name);
1102 token = (*channel)->getConnectionToken();
1103 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001104 }
1105
1106 inputApplicationHandle->updateInfo();
1107 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1108
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001109 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001110 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001111 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001112 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001113 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001114 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001115 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001116 mInfo.globalScaleFactor = 1.0;
1117 mInfo.touchableRegion.clear();
1118 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001119 mInfo.ownerPid = WINDOW_PID;
1120 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001121 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001122 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001123 }
1124
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001125 sp<FakeWindowHandle> clone(int32_t displayId) {
1126 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1127 handle->mInfo = mInfo;
1128 handle->mInfo.displayId = displayId;
1129 handle->mInfo.id = sId++;
1130 handle->mInputReceiver = mInputReceiver;
1131 return handle;
1132 }
1133
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001134 void setTouchable(bool touchable) {
1135 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1136 }
chaviwd1c23182019-12-20 18:44:56 -08001137
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001138 void setFocusable(bool focusable) {
1139 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1140 }
1141
1142 void setVisible(bool visible) {
1143 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1144 }
Vishnu Nair958da932020-08-21 17:12:37 -07001145
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001146 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001147 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001148 }
1149
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001150 void setPaused(bool paused) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1152 }
1153
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001154 void setPreventSplitting(bool preventSplitting) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001156 }
1157
1158 void setSlippery(bool slippery) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1160 }
1161
1162 void setWatchOutsideTouch(bool watchOutside) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1164 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001165
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001166 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1167
1168 void setInterceptsStylus(bool interceptsStylus) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1170 }
1171
1172 void setDropInput(bool dropInput) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1174 }
1175
1176 void setDropInputIfObscured(bool dropInputIfObscured) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1178 }
1179
1180 void setNoInputChannel(bool noInputChannel) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1182 }
1183
Josep del Riob3981622023-04-18 15:49:45 +00001184 void setDisableUserActivity(bool disableUserActivity) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1186 }
1187
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001188 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1190 shouldGlobalStylusBlockTouch);
1191 }
1192
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001193 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1194
chaviw3277faf2021-05-19 16:45:23 -05001195 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001196
Bernardo Rufino7393d172021-02-26 13:56:11 +00001197 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1198
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001199 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001200 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001201 mInfo.touchableRegion.clear();
1202 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001203
1204 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1205 ui::Transform translate;
1206 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1207 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001208 }
1209
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001210 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setIsWallpaper(bool isWallpaper) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1214 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001215
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 void setDupTouchToWallpaper(bool hasWallpaper) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1218 }
chaviwd1c23182019-12-20 18:44:56 -08001219
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001220 void setTrustedOverlay(bool trustedOverlay) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1222 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001223
chaviw9eaa22c2020-07-01 16:21:27 -07001224 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1225 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1226 }
1227
1228 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001229
yunho.shinf4a80b82020-11-16 21:13:57 +09001230 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1231
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001232 const KeyEvent& consumeKey(bool handled = true) {
1233 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1234 if (event.getType() != InputEventType::KEY) {
1235 LOG(FATAL) << "Instead of key event, got " << event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001236 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001237 return static_cast<const KeyEvent&>(event);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001238 }
1239
1240 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001241 const KeyEvent& keyEvent = consumeKey();
1242 ASSERT_THAT(keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001243 }
1244
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001246 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1247 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001248 }
1249
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001250 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001251 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1252 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001253 }
1254
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001256 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001257 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1258 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001259 }
1260
1261 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001262 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001263 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1264 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001265 }
1266
1267 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001268 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001269 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1270 }
1271
1272 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1273 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001274 consumeMotionEvent(
1275 AllOf(WithMotionAction(ACTION_DOWN),
1276 testing::Conditional(expectedDisplayId.has_value(),
1277 WithDisplayId(*expectedDisplayId), testing::_),
1278 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1279 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 }
1281
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1284 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001285 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001287 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1288 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 }
1290
1291 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001293 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001294 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001295 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1296 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 }
1298
1299 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001300 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001301 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1302 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001303 }
1304
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001305 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1306 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001307 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1308 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001309 }
1310
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001311 void consumeMotionOutsideWithZeroedCoords() {
1312 consumeMotionEvent(
1313 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001314 }
1315
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001316 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1320 }
1321
Prabir Pradhan99987712020-11-10 18:43:05 -08001322 void consumeCaptureEvent(bool hasCapture) {
1323 ASSERT_NE(mInputReceiver, nullptr)
1324 << "Cannot consume events from a window with no receiver";
1325 mInputReceiver->consumeCaptureEvent(hasCapture);
1326 }
1327
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001328 const MotionEvent& consumeMotionEvent(
1329 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
1330 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1331 if (event.getType() != InputEventType::MOTION) {
1332 LOG(FATAL) << "Instead of motion event, got " << event;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001333 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001334 const auto& motionEvent = static_cast<const MotionEvent&>(event);
1335 EXPECT_THAT(motionEvent, matcher);
1336 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001354 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
Arthur Hungb92218b2018-08-14 12:00:21 +08001367 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001368 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001369 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001370 return; // Can't receive events if the window does not have input channel
1371 }
1372 ASSERT_NE(nullptr, mInputReceiver)
1373 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001374 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001375 }
1376
chaviwaf87b3e2019-10-01 16:59:28 -07001377 sp<IBinder> getToken() { return mInfo.token; }
1378
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001379 const std::string& getName() { return mName; }
1380
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001381 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001382 mInfo.ownerPid = ownerPid;
1383 mInfo.ownerUid = ownerUid;
1384 }
1385
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001386 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001388 void destroyReceiver() { mInputReceiver = nullptr; }
1389
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001390 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1391
chaviwd1c23182019-12-20 18:44:56 -08001392private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001393 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001394 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001395 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001396 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001397 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001398
1399 const InputEvent& consume(std::chrono::milliseconds timeout, bool handled = true) {
1400 if (mInputReceiver == nullptr) {
1401 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1402 }
1403 InputEvent* event = mInputReceiver->consume(timeout, handled);
1404 if (event == nullptr) {
1405 LOG(FATAL) << "Consume failed: no event";
1406 }
1407 return *event;
1408 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001409};
1410
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001411std::atomic<int32_t> FakeWindowHandle::sId{1};
1412
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001413class FakeMonitorReceiver {
1414public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001415 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1416 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001417
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001418 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001419
1420 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001421 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1422 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001423 }
1424
1425 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001427 }
1428
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001429 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001430
1431 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001432 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1433 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001434 }
1435
1436 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001437 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1438 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001439 }
1440
1441 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001442 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1443 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001444 }
1445
1446 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001447 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001448 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1449 WithDisplayId(expectedDisplayId),
1450 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1451 }
1452
1453 void consumeMotionPointerDown(int32_t pointerIdx) {
1454 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1455 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001456 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1457 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001458 }
1459
1460 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001461 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001462 }
1463
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001464 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001465
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001466 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467
1468private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001469 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001470};
1471
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001472static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001473 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001474 int32_t displayId = ADISPLAY_ID_NONE,
1475 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001476 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001477 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001478 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001479 KeyEvent event;
1480 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1481
1482 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001483 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001484 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1485 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001486
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001487 if (!allowKeyRepeat) {
1488 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1489 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001490 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001491 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001492}
1493
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001494static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1495 InputEventInjectionResult result =
1496 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1497 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1498 if (result != InputEventInjectionResult::TIMED_OUT) {
1499 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1500 }
1501}
1502
1503static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001504 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001505 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001506}
1507
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001508// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1509// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1510// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001511static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1512 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001513 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001514 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001515 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001516}
1517
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001520 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001521}
1522
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001523static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001524 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001525 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001526 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001527 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001528 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1529 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001530}
1531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001533 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1534 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001535 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001536 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1537 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001538 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001539 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001540 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001541 MotionEventBuilder motionBuilder =
1542 MotionEventBuilder(action, source)
1543 .displayId(displayId)
1544 .eventTime(eventTime)
1545 .rawXCursorPosition(cursorPosition.x)
1546 .rawYCursorPosition(cursorPosition.y)
1547 .pointer(
1548 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1549 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1550 motionBuilder.downTime(eventTime);
1551 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001552
1553 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001554 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1555 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001556}
1557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001558static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1559 int32_t displayId,
1560 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001561 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001562}
1563
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001564static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1565 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001566 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001567 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001568}
1569
Jackal Guof9696682018-10-05 12:23:23 +08001570static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1571 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1572 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001573 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1574 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1575 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001576
1577 return args;
1578}
1579
Josep del Riob3981622023-04-18 15:49:45 +00001580static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1581 int32_t displayId = ADISPLAY_ID_NONE) {
1582 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1583 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001584 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1585 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1586 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001587
1588 return args;
1589}
1590
1591static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1592 int32_t displayId = ADISPLAY_ID_NONE) {
1593 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1594 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001595 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1596 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1597 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001598
1599 return args;
1600}
1601
Prabir Pradhan678438e2023-04-13 19:32:51 +00001602[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1603 int32_t displayId,
1604 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001605 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001606 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1607 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1608 }
1609
chaviwd1c23182019-12-20 18:44:56 -08001610 PointerProperties pointerProperties[pointerCount];
1611 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001612
chaviwd1c23182019-12-20 18:44:56 -08001613 for (size_t i = 0; i < pointerCount; i++) {
1614 pointerProperties[i].clear();
1615 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001616 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001617
chaviwd1c23182019-12-20 18:44:56 -08001618 pointerCoords[i].clear();
1619 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1620 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1621 }
Jackal Guof9696682018-10-05 12:23:23 +08001622
1623 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1624 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001625 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1626 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1627 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001628 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001629 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001630 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001631 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001632
1633 return args;
1634}
1635
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001636static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1637 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1638}
1639
chaviwd1c23182019-12-20 18:44:56 -08001640static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1641 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1642}
1643
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001644static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1645 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001646 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1647 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001648}
1649
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001650} // namespace
1651
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001652/**
1653 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1654 * broken channel.
1655 */
1656TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1658 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001659 sp<FakeWindowHandle>::make(application, mDispatcher,
1660 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001661
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001663
1664 // Window closes its channel, but the window remains.
1665 window->destroyReceiver();
1666 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1667}
1668
Arthur Hungb92218b2018-08-14 12:00:21 +08001669TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001671 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1672 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001674 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001676 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001678
1679 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001680 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001681}
1682
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001683TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001685 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1686 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001687
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001688 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001689 // Inject a MotionEvent to an unknown display.
1690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1693
1694 // Window should receive motion event.
1695 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1696}
1697
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001698/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001699 * Calling onWindowInfosChanged once should not cause any issues.
1700 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 * called twice.
1702 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001703TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1706 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714
1715 // Window should receive motion event.
1716 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1717}
1718
1719/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001720 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721 */
1722TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001724 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1725 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001732 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001734
1735 // Window should receive motion event.
1736 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1737}
1738
Arthur Hungb92218b2018-08-14 12:00:21 +08001739// The foreground window should receive the first touch down event.
1740TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001742 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001743 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001744 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001745 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001746
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001747 mDispatcher->onWindowInfosChanged(
1748 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001750 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001751 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001752
1753 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001754 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001755 windowSecond->assertNoEvents();
1756}
1757
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001758/**
1759 * Two windows: A top window, and a wallpaper behind the window.
1760 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1761 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001762 * 1. foregroundWindow <-- dup touch to wallpaper
1763 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001764 */
1765TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1767 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001768 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001769 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001770 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001771 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001772 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001773
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001774 mDispatcher->onWindowInfosChanged(
1775 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001777 injectMotionEvent(*mDispatcher,
1778 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1779 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1780 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1782
1783 // Both foreground window and its wallpaper should receive the touch down
1784 foregroundWindow->consumeMotionDown();
1785 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1786
1787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001788 injectMotionEvent(*mDispatcher,
1789 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1790 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1791 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1793
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001794 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001795 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1796
1797 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001798 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001799 foregroundWindow->consumeMotionCancel();
1800 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1801 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1802}
1803
1804/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001805 * Two fingers down on the window, and lift off the first finger.
1806 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1807 * contains a single pointer.
1808 */
1809TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1811 sp<FakeWindowHandle> window =
1812 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001814 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001815 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1817 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1818 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001819 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001820 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1821 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1822 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1823 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001824 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001825 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1826 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1827 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1828 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001829 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1830 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1831 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1832
1833 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001834 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001835 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1836 window->consumeMotionEvent(
1837 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1838}
1839
1840/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001841 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1842 * with the following differences:
1843 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1844 * clean up the connection.
1845 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1846 * Ensure that there's no crash in the dispatcher.
1847 */
1848TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1850 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001852 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001854 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001855 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001857 mDispatcher->onWindowInfosChanged(
1858 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001860 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001861 {100, 200}))
1862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1863
1864 // Both foreground window and its wallpaper should receive the touch down
1865 foregroundWindow->consumeMotionDown();
1866 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1867
1868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001869 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001870 ADISPLAY_ID_DEFAULT, {110, 200}))
1871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1872
1873 foregroundWindow->consumeMotionMove();
1874 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1875
1876 // Wallpaper closes its channel, but the window remains.
1877 wallpaperWindow->destroyReceiver();
1878 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1879
1880 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1881 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001882 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001883 foregroundWindow->consumeMotionCancel();
1884}
1885
Arthur Hungc539dbb2022-12-08 07:45:36 +00001886class ShouldSplitTouchFixture : public InputDispatcherTest,
1887 public ::testing::WithParamInterface<bool> {};
1888INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1889 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001890/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 * A single window that receives touch (on top), and a wallpaper window underneath it.
1892 * The top window gets a multitouch gesture.
1893 * Ensure that wallpaper gets the same gesture.
1894 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001897 sp<FakeWindowHandle> foregroundWindow =
1898 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1899 foregroundWindow->setDupTouchToWallpaper(true);
1900 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901
1902 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001903 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001904 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001906 mDispatcher->onWindowInfosChanged(
1907 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001908
1909 // Touch down on top window
1910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001911 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 {100, 100}))
1913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1914
1915 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001916 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1918
1919 // Second finger down on the top window
1920 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001921 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001922 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001923 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1924 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 .build();
1926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001927 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001928 InputEventInjectionSync::WAIT_FOR_RESULT))
1929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1930
Harry Cutts33476232023-01-30 19:57:29 +00001931 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1932 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001934
1935 const MotionEvent secondFingerUpEvent =
1936 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1937 .displayId(ADISPLAY_ID_DEFAULT)
1938 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001939 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001941 .build();
1942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001943 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001944 InputEventInjectionSync::WAIT_FOR_RESULT))
1945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1946 foregroundWindow->consumeMotionPointerUp(0);
1947 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1948
1949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001950 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001951 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1952 AINPUT_SOURCE_TOUCHSCREEN)
1953 .displayId(ADISPLAY_ID_DEFAULT)
1954 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001955 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001956 .x(100)
1957 .y(100))
1958 .build(),
1959 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1961 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1962 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963}
1964
1965/**
1966 * Two windows: a window on the left and window on the right.
1967 * A third window, wallpaper, is behind both windows, and spans both top windows.
1968 * The first touch down goes to the left window. A second pointer touches down on the right window.
1969 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1970 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1971 * ACTION_POINTER_DOWN(1).
1972 */
1973TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1975 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001978 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979
1980 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001981 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001982 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001983 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984
1985 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001986 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001988 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001990 mDispatcher->onWindowInfosChanged(
1991 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1992 {},
1993 0,
1994 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995
1996 // Touch down on left window
1997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001998 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 {100, 100}))
2000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2001
2002 // Both foreground window and its wallpaper should receive the touch down
2003 leftWindow->consumeMotionDown();
2004 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2005
2006 // Second finger down on the right window
2007 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002008 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002010 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2011 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 .build();
2013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002014 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 InputEventInjectionSync::WAIT_FOR_RESULT))
2016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2017
2018 leftWindow->consumeMotionMove();
2019 // Since the touch is split, right window gets ACTION_DOWN
2020 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002021 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002022 expectedWallpaperFlags);
2023
2024 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002025 mDispatcher->onWindowInfosChanged(
2026 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 leftWindow->consumeMotionCancel();
2028 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2029 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2030
2031 // The pointer that's still down on the right window moves, and goes to the right window only.
2032 // As far as the dispatcher's concerned though, both pointers are still present.
2033 const MotionEvent secondFingerMoveEvent =
2034 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 .build();
2039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002040 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002041 InputEventInjectionSync::WAIT_FOR_RESULT));
2042 rightWindow->consumeMotionMove();
2043
2044 leftWindow->assertNoEvents();
2045 rightWindow->assertNoEvents();
2046 wallpaperWindow->assertNoEvents();
2047}
2048
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049/**
2050 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2051 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2052 * The right window should receive ACTION_DOWN.
2053 */
2054TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002055 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 sp<FakeWindowHandle> leftWindow =
2057 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2058 leftWindow->setFrame(Rect(0, 0, 200, 200));
2059 leftWindow->setDupTouchToWallpaper(true);
2060 leftWindow->setSlippery(true);
2061
2062 sp<FakeWindowHandle> rightWindow =
2063 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2064 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002065
2066 sp<FakeWindowHandle> wallpaperWindow =
2067 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2068 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002069
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002070 mDispatcher->onWindowInfosChanged(
2071 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2072 {},
2073 0,
2074 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002075
Arthur Hungc539dbb2022-12-08 07:45:36 +00002076 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002078 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002079 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081
2082 // Both foreground window and its wallpaper should receive the touch down
2083 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002084 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2085
Arthur Hungc539dbb2022-12-08 07:45:36 +00002086 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002088 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2091
Arthur Hungc539dbb2022-12-08 07:45:36 +00002092 leftWindow->consumeMotionCancel();
2093 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2094 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002095}
2096
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002097/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002098 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2099 * interactive, it might stop sending this flag.
2100 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2101 * to have a consistent input stream.
2102 *
2103 * Test procedure:
2104 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2105 * DOWN (new gesture).
2106 *
2107 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2108 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2109 *
2110 * We technically just need a single window here, but we are using two windows (spy on top and a
2111 * regular window below) to emulate the actual situation where it happens on the device.
2112 */
2113TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2114 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2115 sp<FakeWindowHandle> spyWindow =
2116 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2117 spyWindow->setFrame(Rect(0, 0, 200, 200));
2118 spyWindow->setTrustedOverlay(true);
2119 spyWindow->setSpy(true);
2120
2121 sp<FakeWindowHandle> window =
2122 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2123 window->setFrame(Rect(0, 0, 200, 200));
2124
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002125 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127
2128 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002129 mDispatcher->notifyMotion(
2130 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2131 .deviceId(touchDeviceId)
2132 .policyFlags(DEFAULT_POLICY_FLAGS)
2133 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2134 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135
Prabir Pradhan678438e2023-04-13 19:32:51 +00002136 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2137 .deviceId(touchDeviceId)
2138 .policyFlags(DEFAULT_POLICY_FLAGS)
2139 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2140 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2141 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002142 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2143 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2144 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2145 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2146
2147 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002148 mDispatcher->notifyMotion(
2149 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2150 .deviceId(touchDeviceId)
2151 .policyFlags(0)
2152 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2153 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2154 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002155 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2156 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2157
2158 // We don't need to reset the device to reproduce the issue, but the reset event typically
2159 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002160 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002161
2162 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002163 mDispatcher->notifyMotion(
2164 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2165 .deviceId(touchDeviceId)
2166 .policyFlags(DEFAULT_POLICY_FLAGS)
2167 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2168 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002169 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2170 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2171
2172 // No more events
2173 spyWindow->assertNoEvents();
2174 window->assertNoEvents();
2175}
2176
2177/**
Linnan Li907ae732023-09-05 17:14:21 +08002178 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2179 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2180 * interactive, it might stop sending this flag.
2181 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2182 * the consistency of the hover event in this case.
2183 *
2184 * Test procedure:
2185 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2186 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2187 *
2188 * We expect to receive two full streams of hover events.
2189 */
2190TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2192
2193 sp<FakeWindowHandle> window =
2194 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2195 window->setFrame(Rect(0, 0, 300, 300));
2196
2197 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2198
2199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2200 .policyFlags(DEFAULT_POLICY_FLAGS)
2201 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2202 .build());
2203 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2204
2205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2206 .policyFlags(DEFAULT_POLICY_FLAGS)
2207 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2208 .build());
2209 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2210
2211 // Send hover exit without the default policy flags.
2212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2213 .policyFlags(0)
2214 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2215 .build());
2216
2217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2218
2219 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2220 // right event.
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2222 .policyFlags(DEFAULT_POLICY_FLAGS)
2223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2224 .build());
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2226
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2228 .policyFlags(DEFAULT_POLICY_FLAGS)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2230 .build());
2231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2232
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2234 .policyFlags(DEFAULT_POLICY_FLAGS)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2236 .build());
2237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2238}
2239
2240/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002241 * Two windows: a window on the left and a window on the right.
2242 * Mouse is hovered from the right window into the left window.
2243 * Next, we tap on the left window, where the cursor was last seen.
2244 * The second tap is done onto the right window.
2245 * The mouse and tap are from two different devices.
2246 * We technically don't need to set the downtime / eventtime for these events, but setting these
2247 * explicitly helps during debugging.
2248 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2249 * In the buggy implementation, a tap on the right window would cause a crash.
2250 */
2251TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2253 sp<FakeWindowHandle> leftWindow =
2254 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2255 leftWindow->setFrame(Rect(0, 0, 200, 200));
2256
2257 sp<FakeWindowHandle> rightWindow =
2258 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2259 rightWindow->setFrame(Rect(200, 0, 400, 200));
2260
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002261 mDispatcher->onWindowInfosChanged(
2262 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002263 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2264 // stale.
2265 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2266 const int32_t mouseDeviceId = 6;
2267 const int32_t touchDeviceId = 4;
2268 // Move the cursor from right
2269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2272 AINPUT_SOURCE_MOUSE)
2273 .deviceId(mouseDeviceId)
2274 .downTime(baseTime + 10)
2275 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 .build()));
2278 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2279
2280 // .. to the left window
2281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002283 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2284 AINPUT_SOURCE_MOUSE)
2285 .deviceId(mouseDeviceId)
2286 .downTime(baseTime + 10)
2287 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 .build()));
2290 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2291 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2292 // Now tap the left window
2293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002294 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002295 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2296 AINPUT_SOURCE_TOUCHSCREEN)
2297 .deviceId(touchDeviceId)
2298 .downTime(baseTime + 40)
2299 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002300 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002301 .build()));
2302 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2303 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2304
2305 // release tap
2306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002307 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2309 AINPUT_SOURCE_TOUCHSCREEN)
2310 .deviceId(touchDeviceId)
2311 .downTime(baseTime + 40)
2312 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 .build()));
2315 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2316
2317 // Tap the window on the right
2318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002319 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2321 AINPUT_SOURCE_TOUCHSCREEN)
2322 .deviceId(touchDeviceId)
2323 .downTime(baseTime + 60)
2324 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002325 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002326 .build()));
2327 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2328
2329 // release tap
2330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002331 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2333 AINPUT_SOURCE_TOUCHSCREEN)
2334 .deviceId(touchDeviceId)
2335 .downTime(baseTime + 60)
2336 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002337 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002338 .build()));
2339 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2340
2341 // No more events
2342 leftWindow->assertNoEvents();
2343 rightWindow->assertNoEvents();
2344}
2345
2346/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002347 * Start hovering in a window. While this hover is still active, make another window appear on top.
2348 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2349 * While the top window is present, the hovering is stopped.
2350 * Later, hovering gets resumed again.
2351 * Ensure that new hover gesture is handled correctly.
2352 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2353 * to the window that's currently being hovered over.
2354 */
2355TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2357 sp<FakeWindowHandle> window =
2358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2359 window->setFrame(Rect(0, 0, 200, 200));
2360
2361 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002362 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002363
2364 // Start hovering in the window
2365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2366 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2367 .build());
2368 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2369
2370 // Now, an obscuring window appears!
2371 sp<FakeWindowHandle> obscuringWindow =
2372 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2373 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002374 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002375 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2376 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2377 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2378 obscuringWindow->setNoInputChannel(true);
2379 obscuringWindow->setFocusable(false);
2380 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002381 mDispatcher->onWindowInfosChanged(
2382 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002383
2384 // While this new obscuring window is present, the hovering is stopped
2385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2386 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2387 .build());
2388 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2389
2390 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002392
2393 // And a new hover gesture starts.
2394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2396 .build());
2397 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2398}
2399
2400/**
2401 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2402 * the obscuring window.
2403 */
2404TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2406 sp<FakeWindowHandle> window =
2407 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2408 window->setFrame(Rect(0, 0, 200, 200));
2409
2410 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002411 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002412
2413 // Start hovering in the window
2414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2415 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2416 .build());
2417 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2418
2419 // Now, an obscuring window appears!
2420 sp<FakeWindowHandle> obscuringWindow =
2421 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2422 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002423 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002424 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2425 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2426 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2427 obscuringWindow->setNoInputChannel(true);
2428 obscuringWindow->setFocusable(false);
2429 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002430 mDispatcher->onWindowInfosChanged(
2431 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002432
2433 // While this new obscuring window is present, the hovering continues. The event can't go to the
2434 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2435 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2436 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2437 .build());
2438 obscuringWindow->assertNoEvents();
2439 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2440
2441 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002442 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002443
2444 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2445 // so it should generate a HOVER_ENTER
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2447 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2448 .build());
2449 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2450
2451 // Now the MOVE should be getting dispatched normally
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2453 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2456}
2457
2458/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002459 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2460 * events are delivered to the window.
2461 */
2462TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 window->setFrame(Rect(0, 0, 200, 200));
2467 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2468
2469 // Start hovering in the window
2470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2472 .build());
2473 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2474
2475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2476 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2477 .build());
2478 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2479
2480 // Scroll with the mouse
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2482 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2483 .build());
2484 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2485}
2486
2487using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2488
2489/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002490 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2491 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002492 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002493TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2495 sp<FakeWindowHandle> window =
2496 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2497 window->setFrame(Rect(0, 0, 200, 200));
2498
2499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2500
2501 constexpr int32_t touchDeviceId = 4;
2502 constexpr int32_t stylusDeviceId = 2;
2503
2504 // Stylus down
2505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2506 .deviceId(stylusDeviceId)
2507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2508 .build());
2509 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2510
2511 // Touch down
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2513 .deviceId(touchDeviceId)
2514 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2515 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002516
2517 // Touch move
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2521 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002522 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002523
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002524 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2526 .deviceId(stylusDeviceId)
2527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2528 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002529 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2530 WithCoords(101, 111)));
2531
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002532 window->assertNoEvents();
2533}
2534
2535/**
2536 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002537 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002538 * Similar test as above, but with added SPY window.
2539 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002540TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2542 sp<FakeWindowHandle> window =
2543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2544 sp<FakeWindowHandle> spyWindow =
2545 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2546 spyWindow->setFrame(Rect(0, 0, 200, 200));
2547 spyWindow->setTrustedOverlay(true);
2548 spyWindow->setSpy(true);
2549 window->setFrame(Rect(0, 0, 200, 200));
2550
2551 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2552
2553 constexpr int32_t touchDeviceId = 4;
2554 constexpr int32_t stylusDeviceId = 2;
2555
2556 // Stylus down
2557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2558 .deviceId(stylusDeviceId)
2559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2560 .build());
2561 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2562 spyWindow->consumeMotionEvent(
2563 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2564
2565 // Touch down
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2567 .deviceId(touchDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2569 .build());
2570
2571 // Touch move
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2573 .deviceId(touchDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2575 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002576
2577 // Touch is ignored because stylus is already down
2578
2579 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2581 .deviceId(stylusDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2583 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2585 WithCoords(101, 111)));
2586 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2587 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002588
2589 window->assertNoEvents();
2590 spyWindow->assertNoEvents();
2591}
2592
2593/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002594 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002595 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002596 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002597TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2599 sp<FakeWindowHandle> window =
2600 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2601 window->setFrame(Rect(0, 0, 200, 200));
2602
2603 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2604
2605 constexpr int32_t touchDeviceId = 4;
2606 constexpr int32_t stylusDeviceId = 2;
2607
2608 // Stylus down on the window
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2610 .deviceId(stylusDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2612 .build());
2613 window->consumeMotionEvent(
2614 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2615
2616 // Touch down on window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2618 .deviceId(touchDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2620 .build());
2621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2622 .deviceId(touchDeviceId)
2623 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2624 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002625
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002626 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002627
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002628 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2630 .deviceId(stylusDeviceId)
2631 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2632 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002633 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2634 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002635
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002636 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2638 .deviceId(touchDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2640 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002641 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002642}
2643
2644/**
2645 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002646 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002647 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002648TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2650 sp<FakeWindowHandle> window =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2652 window->setFrame(Rect(0, 0, 200, 200));
2653
2654 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2655
2656 constexpr int32_t touchDeviceId = 4;
2657 constexpr int32_t stylusDeviceId = 2;
2658
2659 // Touch down on window
2660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2661 .deviceId(touchDeviceId)
2662 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2663 .build());
2664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2665 .deviceId(touchDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2667 .build());
2668 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2669 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2670
2671 // Stylus hover on the window
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2673 .deviceId(stylusDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2675 .build());
2676 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2677 .deviceId(stylusDeviceId)
2678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2679 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002680 // Stylus hover movement causes touch to be canceled
2681 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2682 WithCoords(141, 146)));
2683 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2684 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2685 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2686 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002687
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002688 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2690 .deviceId(touchDeviceId)
2691 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2692 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002693
2694 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002695}
2696
2697/**
2698 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2699 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2700 * become active.
2701 */
2702TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2704 sp<FakeWindowHandle> window =
2705 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2706 window->setFrame(Rect(0, 0, 200, 200));
2707
2708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2709
2710 constexpr int32_t stylusDeviceId1 = 3;
2711 constexpr int32_t stylusDeviceId2 = 5;
2712
2713 // Touch down on window
2714 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2715 .deviceId(stylusDeviceId1)
2716 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2717 .build());
2718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2719 .deviceId(stylusDeviceId1)
2720 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2721 .build());
2722 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2723 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2724
2725 // Second stylus down
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId2)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2729 .build());
2730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2731 .deviceId(stylusDeviceId2)
2732 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2733 .build());
2734
2735 // First stylus is canceled, second one takes over.
2736 window->consumeMotionEvent(
2737 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2738 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2739 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2740
2741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2742 .deviceId(stylusDeviceId1)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2744 .build());
2745 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002746 window->assertNoEvents();
2747}
2748
2749/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002750 * One window. Touch down on the window. Then, stylus down on the window from another device.
2751 * Ensure that is canceled, because stylus down should be preferred over touch.
2752 */
2753TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2754 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2755 sp<FakeWindowHandle> window =
2756 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2757 window->setFrame(Rect(0, 0, 200, 200));
2758
2759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2760
2761 constexpr int32_t touchDeviceId = 4;
2762 constexpr int32_t stylusDeviceId = 2;
2763
2764 // Touch down on window
2765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2766 .deviceId(touchDeviceId)
2767 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2768 .build());
2769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2770 .deviceId(touchDeviceId)
2771 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2772 .build());
2773 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2775
2776 // Stylus down on the window
2777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2778 .deviceId(stylusDeviceId)
2779 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2780 .build());
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2783
2784 // Subsequent stylus movements are delivered correctly
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2786 .deviceId(stylusDeviceId)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2790 WithCoords(101, 111)));
2791}
2792
2793/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002794 * Two windows: a window on the left and a window on the right.
2795 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2796 * down. Then, on the left window, also place second touch pointer down.
2797 * This test tries to reproduce a crash.
2798 * In the buggy implementation, second pointer down on the left window would cause a crash.
2799 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002800TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2802 sp<FakeWindowHandle> leftWindow =
2803 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2804 leftWindow->setFrame(Rect(0, 0, 200, 200));
2805
2806 sp<FakeWindowHandle> rightWindow =
2807 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2808 rightWindow->setFrame(Rect(200, 0, 400, 200));
2809
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002810 mDispatcher->onWindowInfosChanged(
2811 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812
2813 const int32_t touchDeviceId = 4;
2814 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815
2816 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2818 .deviceId(mouseDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2820 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821 leftWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2823
2824 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2826 .deviceId(mouseDeviceId)
2827 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2829 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002830
2831 leftWindow->consumeMotionEvent(
2832 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2833 leftWindow->consumeMotionEvent(
2834 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2835
Prabir Pradhan678438e2023-04-13 19:32:51 +00002836 mDispatcher->notifyMotion(
2837 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2838 .deviceId(mouseDeviceId)
2839 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2840 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2842 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002843 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2844
2845 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2847 .deviceId(touchDeviceId)
2848 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2849 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002850 leftWindow->assertNoEvents();
2851
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2853
2854 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002855 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2856 .deviceId(touchDeviceId)
2857 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2858 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2859 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002860 // Since this is now a new splittable pointer going down on the left window, and it's coming
2861 // from a different device, the current gesture in the left window (pointer down) should first
2862 // be canceled.
2863 leftWindow->consumeMotionEvent(
2864 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865 leftWindow->consumeMotionEvent(
2866 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2867 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2868 // current implementation.
2869 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2870 rightWindow->consumeMotionEvent(
2871 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2872
2873 leftWindow->assertNoEvents();
2874 rightWindow->assertNoEvents();
2875}
2876
2877/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002878 * Two windows: a window on the left and a window on the right.
2879 * Mouse is hovered on the left window and stylus is hovered on the right window.
2880 */
2881TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2883 sp<FakeWindowHandle> leftWindow =
2884 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2885 leftWindow->setFrame(Rect(0, 0, 200, 200));
2886
2887 sp<FakeWindowHandle> rightWindow =
2888 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2889 rightWindow->setFrame(Rect(200, 0, 400, 200));
2890
2891 mDispatcher->onWindowInfosChanged(
2892 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2893
2894 const int32_t stylusDeviceId = 3;
2895 const int32_t mouseDeviceId = 6;
2896
2897 // Start hovering over the left window
2898 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2899 .deviceId(mouseDeviceId)
2900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2901 .build());
2902 leftWindow->consumeMotionEvent(
2903 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2904
2905 // Stylus hovered on right window
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2907 .deviceId(stylusDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2909 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002910 rightWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2912
2913 // Subsequent HOVER_MOVE events are dispatched correctly.
2914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2915 .deviceId(mouseDeviceId)
2916 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2917 .build());
2918 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002919 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002920
2921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2922 .deviceId(stylusDeviceId)
2923 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2924 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002926 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002927
2928 leftWindow->assertNoEvents();
2929 rightWindow->assertNoEvents();
2930}
2931
2932/**
2933 * Three windows: a window on the left and a window on the right.
2934 * And a spy window that's positioned above all of them.
2935 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2936 * Check the stream that's received by the spy.
2937 */
2938TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940
2941 sp<FakeWindowHandle> spyWindow =
2942 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2943 spyWindow->setFrame(Rect(0, 0, 400, 400));
2944 spyWindow->setTrustedOverlay(true);
2945 spyWindow->setSpy(true);
2946
2947 sp<FakeWindowHandle> leftWindow =
2948 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2949 leftWindow->setFrame(Rect(0, 0, 200, 200));
2950
2951 sp<FakeWindowHandle> rightWindow =
2952 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2953
2954 rightWindow->setFrame(Rect(200, 0, 400, 200));
2955
2956 mDispatcher->onWindowInfosChanged(
2957 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2958
2959 const int32_t stylusDeviceId = 1;
2960 const int32_t touchDeviceId = 2;
2961
2962 // Stylus down on the left window
2963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2964 .deviceId(stylusDeviceId)
2965 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2966 .build());
2967 leftWindow->consumeMotionEvent(
2968 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2969 spyWindow->consumeMotionEvent(
2970 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2971
2972 // Touch down on the right window
2973 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2974 .deviceId(touchDeviceId)
2975 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2976 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002977 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002978 rightWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002980
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002981 // Spy window does not receive touch events, because stylus events take precedence, and it
2982 // already has an active stylus gesture.
2983
2984 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2986 .deviceId(stylusDeviceId)
2987 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2988 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002989 leftWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2991 spyWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002994 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2996 .deviceId(touchDeviceId)
2997 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2998 .build());
2999 rightWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001
3002 spyWindow->assertNoEvents();
3003 leftWindow->assertNoEvents();
3004 rightWindow->assertNoEvents();
3005}
3006
3007/**
3008 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3009 * both.
3010 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003011 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003012 * At the same time, left and right should be getting independent streams of hovering and touch,
3013 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003014 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003015TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3017
3018 sp<FakeWindowHandle> spyWindow =
3019 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3020 spyWindow->setFrame(Rect(0, 0, 400, 400));
3021 spyWindow->setTrustedOverlay(true);
3022 spyWindow->setSpy(true);
3023
3024 sp<FakeWindowHandle> leftWindow =
3025 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3026 leftWindow->setFrame(Rect(0, 0, 200, 200));
3027
3028 sp<FakeWindowHandle> rightWindow =
3029 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3030 rightWindow->setFrame(Rect(200, 0, 400, 200));
3031
3032 mDispatcher->onWindowInfosChanged(
3033 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3034
3035 const int32_t stylusDeviceId = 1;
3036 const int32_t touchDeviceId = 2;
3037
3038 // Stylus hover on the left window
3039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3040 .deviceId(stylusDeviceId)
3041 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3042 .build());
3043 leftWindow->consumeMotionEvent(
3044 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3045 spyWindow->consumeMotionEvent(
3046 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3047
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003048 // Touch down on the right window. Spy doesn't receive this touch because it already has
3049 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3051 .deviceId(touchDeviceId)
3052 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3053 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003054 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003055 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003056 rightWindow->consumeMotionEvent(
3057 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3058
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003059 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3061 .deviceId(stylusDeviceId)
3062 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3063 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003064 leftWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003066 spyWindow->consumeMotionEvent(
3067 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003069 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3071 .deviceId(touchDeviceId)
3072 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3073 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 rightWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3076
3077 spyWindow->assertNoEvents();
3078 leftWindow->assertNoEvents();
3079 rightWindow->assertNoEvents();
3080}
3081
3082/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003083 * On a single window, use two different devices: mouse and touch.
3084 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3085 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3086 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3087 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3088 * represent a new gesture.
3089 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003090TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3092 sp<FakeWindowHandle> window =
3093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3094 window->setFrame(Rect(0, 0, 400, 400));
3095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003097
3098 const int32_t touchDeviceId = 4;
3099 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003101 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003102 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3110 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3114 .deviceId(touchDeviceId)
3115 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3116 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3117 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3119 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3120 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3121
3122 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3124 .deviceId(mouseDeviceId)
3125 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3127 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003128
3129 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003130 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003131 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3132
Prabir Pradhan678438e2023-04-13 19:32:51 +00003133 mDispatcher->notifyMotion(
3134 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3135 .deviceId(mouseDeviceId)
3136 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3137 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3139 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3141
3142 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003143 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3144 .deviceId(touchDeviceId)
3145 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3146 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3147 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003148 // Since we already canceled this touch gesture, it will be ignored until a completely new
3149 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3150 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3151 // However, mouse movements should continue to work.
3152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3153 .deviceId(mouseDeviceId)
3154 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3155 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3156 .build());
3157 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3158
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003159 window->assertNoEvents();
3160}
3161
3162/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003163 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3164 * the injected event.
3165 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003166TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3168 sp<FakeWindowHandle> window =
3169 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3170 window->setFrame(Rect(0, 0, 400, 400));
3171
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003172 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003173
3174 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003175 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3176 // completion.
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003179 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3180 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003181 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003182 .build()));
3183 window->consumeMotionEvent(
3184 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3185
3186 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3187 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3189 .deviceId(touchDeviceId)
3190 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3191 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003192
3193 window->consumeMotionEvent(
3194 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3195 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3196}
3197
3198/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003199 * This test is similar to the test above, but the sequence of injected events is different.
3200 *
3201 * Two windows: a window on the left and a window on the right.
3202 * Mouse is hovered over the left window.
3203 * Next, we tap on the left window, where the cursor was last seen.
3204 *
3205 * After that, we inject one finger down onto the right window, and then a second finger down onto
3206 * the left window.
3207 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3208 * window (first), and then another on the left window (second).
3209 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3210 * In the buggy implementation, second finger down on the left window would cause a crash.
3211 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003212TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3214 sp<FakeWindowHandle> leftWindow =
3215 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3216 leftWindow->setFrame(Rect(0, 0, 200, 200));
3217
3218 sp<FakeWindowHandle> rightWindow =
3219 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3220 rightWindow->setFrame(Rect(200, 0, 400, 200));
3221
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003222 mDispatcher->onWindowInfosChanged(
3223 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003224
3225 const int32_t mouseDeviceId = 6;
3226 const int32_t touchDeviceId = 4;
3227 // Hover over the left window. Keep the cursor there.
3228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003229 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003230 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3231 AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003233 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003234 .build()));
3235 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3236
3237 // Tap on left window
3238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003240 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3241 AINPUT_SOURCE_TOUCHSCREEN)
3242 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003243 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003244 .build()));
3245
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003248 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252 .build()));
3253 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3254 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3255 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3256
3257 // First finger down on right window
3258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003260 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3261 AINPUT_SOURCE_TOUCHSCREEN)
3262 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003263 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003264 .build()));
3265 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3266
3267 // Second finger down on the left window
3268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003269 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003270 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3271 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003272 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3273 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003274 .build()));
3275 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3276 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3277
3278 // No more events
3279 leftWindow->assertNoEvents();
3280 rightWindow->assertNoEvents();
3281}
3282
3283/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003284 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3285 * While the touch is down, new hover events from the stylus device should be ignored. After the
3286 * touch is gone, stylus hovering should start working again.
3287 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003288TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003289 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3290 sp<FakeWindowHandle> window =
3291 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3292 window->setFrame(Rect(0, 0, 200, 200));
3293
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003294 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003295
3296 const int32_t stylusDeviceId = 5;
3297 const int32_t touchDeviceId = 4;
3298 // Start hovering with stylus
3299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003300 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003301 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003302 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003303 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003304 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003305 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003306
3307 // Finger down on the window
3308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003309 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003310 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003311 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003314 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003315
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003316 // Continue hovering with stylus.
3317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3320 AINPUT_SOURCE_STYLUS)
3321 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003323 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003324 // Hovers continue to work
3325 window->consumeMotionEvent(
3326 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003327
3328 // Lift up the finger
3329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003330 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3332 AINPUT_SOURCE_TOUCHSCREEN)
3333 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003334 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003336
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003338 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3340 AINPUT_SOURCE_STYLUS)
3341 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003342 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003344 window->consumeMotionEvent(
3345 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003346 window->assertNoEvents();
3347}
3348
3349/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003350 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3351 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3352 *
3353 * Two windows: one on the left and one on the right.
3354 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3355 * Stylus down on the left window, and then touch down on the right window.
3356 * Check that the right window doesn't get touches while the stylus is down on the left window.
3357 */
3358TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3360 sp<FakeWindowHandle> leftWindow =
3361 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3362 ADISPLAY_ID_DEFAULT);
3363 leftWindow->setFrame(Rect(0, 0, 100, 100));
3364
3365 sp<FakeWindowHandle> sbtRightWindow =
3366 sp<FakeWindowHandle>::make(application, mDispatcher,
3367 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3368 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3369 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3370
3371 mDispatcher->onWindowInfosChanged(
3372 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3373
3374 const int32_t stylusDeviceId = 5;
3375 const int32_t touchDeviceId = 4;
3376
3377 // Stylus down in the left window
3378 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3379 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3380 .deviceId(stylusDeviceId)
3381 .build());
3382 leftWindow->consumeMotionEvent(
3383 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3384
3385 // Finger tap on the right window
3386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3387 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3388 .deviceId(touchDeviceId)
3389 .build());
3390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3391 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3392 .deviceId(touchDeviceId)
3393 .build());
3394
3395 // The touch should be blocked, because stylus is down somewhere else on screen!
3396 sbtRightWindow->assertNoEvents();
3397
3398 // Continue stylus motion, and ensure it's not impacted.
3399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3400 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3401 .deviceId(stylusDeviceId)
3402 .build());
3403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3405 .deviceId(stylusDeviceId)
3406 .build());
3407 leftWindow->consumeMotionEvent(
3408 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3409 leftWindow->consumeMotionEvent(
3410 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3411
3412 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3414 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3415 .deviceId(touchDeviceId)
3416 .build());
3417 sbtRightWindow->consumeMotionEvent(
3418 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3419}
3420
3421/**
3422 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3423 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3424 *
3425 * Two windows: one on the left and one on the right.
3426 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3427 * Stylus hover on the left window, and then touch down on the right window.
3428 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3429 */
3430TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3432 sp<FakeWindowHandle> leftWindow =
3433 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3434 ADISPLAY_ID_DEFAULT);
3435 leftWindow->setFrame(Rect(0, 0, 100, 100));
3436
3437 sp<FakeWindowHandle> sbtRightWindow =
3438 sp<FakeWindowHandle>::make(application, mDispatcher,
3439 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3440 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3441 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3442
3443 mDispatcher->onWindowInfosChanged(
3444 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3445
3446 const int32_t stylusDeviceId = 5;
3447 const int32_t touchDeviceId = 4;
3448
3449 // Stylus hover in the left window
3450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3451 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3452 .deviceId(stylusDeviceId)
3453 .build());
3454 leftWindow->consumeMotionEvent(
3455 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3456
3457 // Finger tap on the right window
3458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3459 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3460 .deviceId(touchDeviceId)
3461 .build());
3462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3463 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3464 .deviceId(touchDeviceId)
3465 .build());
3466
3467 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3468 sbtRightWindow->assertNoEvents();
3469
3470 // Continue stylus motion, and ensure it's not impacted.
3471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3472 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3473 .deviceId(stylusDeviceId)
3474 .build());
3475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3476 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3477 .deviceId(stylusDeviceId)
3478 .build());
3479 leftWindow->consumeMotionEvent(
3480 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3481 leftWindow->consumeMotionEvent(
3482 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3483
3484 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3485 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3486 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3487 .deviceId(touchDeviceId)
3488 .build());
3489 sbtRightWindow->consumeMotionEvent(
3490 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3491}
3492
3493/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003494 * A spy window above a window with no input channel.
3495 * Start hovering with a stylus device, and then tap with it.
3496 * Ensure spy window receives the entire sequence.
3497 */
3498TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3500 sp<FakeWindowHandle> spyWindow =
3501 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3502 spyWindow->setFrame(Rect(0, 0, 200, 200));
3503 spyWindow->setTrustedOverlay(true);
3504 spyWindow->setSpy(true);
3505 sp<FakeWindowHandle> window =
3506 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3507 window->setNoInputChannel(true);
3508 window->setFrame(Rect(0, 0, 200, 200));
3509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003510 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003511
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003512 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3514 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003516 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3517 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3522
3523 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3525 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003527 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3528
3529 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003530 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3531 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3532 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003533 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3534
3535 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3538 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003539 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3540 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3542 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3543 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003544 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3545
3546 // No more events
3547 spyWindow->assertNoEvents();
3548 window->assertNoEvents();
3549}
3550
3551/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003552 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3553 * rejected. But since we already have an ongoing gesture, this event should be processed.
3554 * This prevents inconsistent events being handled inside the dispatcher.
3555 */
3556TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3558
3559 sp<FakeWindowHandle> window =
3560 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3561 window->setFrame(Rect(0, 0, 200, 200));
3562
3563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3564
3565 // Start hovering with stylus
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3568 .build());
3569 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3570
3571 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3572 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3573 .build();
3574 // Make this 'hoverExit' event stale
3575 mFakePolicy->setStaleEventTimeout(100ms);
3576 std::this_thread::sleep_for(100ms);
3577
3578 // It shouldn't be dropped by the dispatcher, even though it's stale.
3579 mDispatcher->notifyMotion(hoverExit);
3580 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3581
3582 // Stylus starts hovering again! There should be no crash.
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3585 .build());
3586 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3587}
3588
3589/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003590 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3591 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3592 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3593 * While the mouse is down, new move events from the touch device should be ignored.
3594 */
3595TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3597 sp<FakeWindowHandle> spyWindow =
3598 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3599 spyWindow->setFrame(Rect(0, 0, 200, 200));
3600 spyWindow->setTrustedOverlay(true);
3601 spyWindow->setSpy(true);
3602 sp<FakeWindowHandle> window =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3604 window->setFrame(Rect(0, 0, 200, 200));
3605
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003606 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003607
3608 const int32_t mouseDeviceId = 7;
3609 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003610
3611 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3613 .deviceId(mouseDeviceId)
3614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3615 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003616 spyWindow->consumeMotionEvent(
3617 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3618 window->consumeMotionEvent(
3619 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3620
3621 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3623 .deviceId(touchDeviceId)
3624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3625 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003626 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3627 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3628 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3629 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3630
Prabir Pradhan678438e2023-04-13 19:32:51 +00003631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3632 .deviceId(touchDeviceId)
3633 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3636 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3637
3638 // Pilfer the stream
3639 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3640 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3641
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3643 .deviceId(touchDeviceId)
3644 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3645 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003646 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3647
3648 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3650 .deviceId(mouseDeviceId)
3651 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3652 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003654
3655 spyWindow->consumeMotionEvent(
3656 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3657 spyWindow->consumeMotionEvent(
3658 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3659 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3660
Prabir Pradhan678438e2023-04-13 19:32:51 +00003661 mDispatcher->notifyMotion(
3662 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3663 .deviceId(mouseDeviceId)
3664 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3665 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003668 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3669 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3670
3671 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3673 .deviceId(mouseDeviceId)
3674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003677 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3678 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3679
3680 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3682 .deviceId(touchDeviceId)
3683 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3684 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003685
3686 // No more events
3687 spyWindow->assertNoEvents();
3688 window->assertNoEvents();
3689}
3690
3691/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003692 * On the display, have a single window, and also an area where there's no window.
3693 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3694 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3695 */
3696TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3698 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003699 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003700
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003701 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003702
3703 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003704 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003705
3706 mDispatcher->waitForIdle();
3707 window->assertNoEvents();
3708
3709 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003710 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003711 mDispatcher->waitForIdle();
3712 window->consumeMotionDown();
3713}
3714
3715/**
3716 * Same test as above, but instead of touching the empty space, the first touch goes to
3717 * non-touchable window.
3718 */
3719TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3721 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003722 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003723 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3724 window1->setTouchable(false);
3725 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003727 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3728
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003729 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003730
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003731 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003732 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003733
3734 mDispatcher->waitForIdle();
3735 window1->assertNoEvents();
3736 window2->assertNoEvents();
3737
3738 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003740 mDispatcher->waitForIdle();
3741 window2->consumeMotionDown();
3742}
3743
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003744/**
3745 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3746 * to the event time of the first ACTION_DOWN sent to the particular window.
3747 */
3748TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3750 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003751 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003752 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3753 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003754 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003755 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003757 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003758
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003759 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003761
3762 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003763
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003764 const MotionEvent& motionEvent1 = window1->consumeMotionEvent();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003765 window2->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003766 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3767 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003768
3769 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003770 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003771 mDispatcher->waitForIdle();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003772 const MotionEvent& motionEvent2 = window2->consumeMotionEvent();
3773 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003774 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003775 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003776
3777 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003779 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003780 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003781
3782 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003783 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003784 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003785 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003786
3787 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3788 window1->consumeMotionMove();
3789 window1->assertNoEvents();
3790
3791 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003792 mDispatcher->notifyMotion(
3793 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003794 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003795 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003796
Prabir Pradhan678438e2023-04-13 19:32:51 +00003797 mDispatcher->notifyMotion(
3798 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003799 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003800 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003801}
3802
Garfield Tandf26e862020-07-01 20:18:19 -07003803TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003805 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003806 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003807 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003808 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003809 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003810 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003811
3812 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003814 mDispatcher->onWindowInfosChanged(
3815 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003816
3817 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003819 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003820 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3821 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003822 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003823 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003824 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003825
3826 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003828 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003829 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3830 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003831 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003832 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003833 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3834 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003835
3836 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003838 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003839 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3840 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003842 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003843 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3844 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003845
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003847 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003848 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3849 AINPUT_SOURCE_MOUSE)
3850 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3851 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003853 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003854 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003855
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003857 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003858 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3859 AINPUT_SOURCE_MOUSE)
3860 .buttonState(0)
3861 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003862 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003863 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003864 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003865
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003867 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003868 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3869 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003870 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003871 .build()));
3872 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3873
3874 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003876 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003877 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3878 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003879 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003880 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003881 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003882
3883 // No more events
3884 windowLeft->assertNoEvents();
3885 windowRight->assertNoEvents();
3886}
3887
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003888/**
3889 * Put two fingers down (and don't release them) and click the mouse button.
3890 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3891 * currently active gesture should be canceled, and the new one should proceed.
3892 */
3893TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3895 sp<FakeWindowHandle> window =
3896 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3897 window->setFrame(Rect(0, 0, 600, 800));
3898
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003899 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003900
3901 const int32_t touchDeviceId = 4;
3902 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003903
3904 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3906 .deviceId(touchDeviceId)
3907 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3908 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003909
Prabir Pradhan678438e2023-04-13 19:32:51 +00003910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3911 .deviceId(touchDeviceId)
3912 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3913 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3914 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003915 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3916 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3917
3918 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3920 .deviceId(mouseDeviceId)
3921 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3923 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003924 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3925 WithPointerCount(2u)));
3926 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3927
Prabir Pradhan678438e2023-04-13 19:32:51 +00003928 mDispatcher->notifyMotion(
3929 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3930 .deviceId(mouseDeviceId)
3931 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3932 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3934 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3936
3937 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3938 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003939 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3940 .deviceId(touchDeviceId)
3941 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3942 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3943 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003944 window->assertNoEvents();
3945}
3946
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003947TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3949
3950 sp<FakeWindowHandle> spyWindow =
3951 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3952 spyWindow->setFrame(Rect(0, 0, 600, 800));
3953 spyWindow->setTrustedOverlay(true);
3954 spyWindow->setSpy(true);
3955 sp<FakeWindowHandle> window =
3956 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3957 window->setFrame(Rect(0, 0, 600, 800));
3958
3959 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003960 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003961
3962 // Send mouse cursor to the window
3963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003965 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3966 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003968 .build()));
3969
3970 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3971 WithSource(AINPUT_SOURCE_MOUSE)));
3972 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3973 WithSource(AINPUT_SOURCE_MOUSE)));
3974
3975 window->assertNoEvents();
3976 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003977}
3978
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003979TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3981
3982 sp<FakeWindowHandle> spyWindow =
3983 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3984 spyWindow->setFrame(Rect(0, 0, 600, 800));
3985 spyWindow->setTrustedOverlay(true);
3986 spyWindow->setSpy(true);
3987 sp<FakeWindowHandle> window =
3988 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3989 window->setFrame(Rect(0, 0, 600, 800));
3990
3991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003992 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003993
3994 // Send mouse cursor to the window
3995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003996 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3998 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004000 .build()));
4001
4002 // Move mouse cursor
4003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004004 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004005 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4006 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004007 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004008 .build()));
4009
4010 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4011 WithSource(AINPUT_SOURCE_MOUSE)));
4012 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4013 WithSource(AINPUT_SOURCE_MOUSE)));
4014 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4015 WithSource(AINPUT_SOURCE_MOUSE)));
4016 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4017 WithSource(AINPUT_SOURCE_MOUSE)));
4018 // Touch down on the window
4019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004020 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004021 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4022 AINPUT_SOURCE_TOUCHSCREEN)
4023 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004024 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004025 .build()));
4026 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4027 WithSource(AINPUT_SOURCE_MOUSE)));
4028 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4029 WithSource(AINPUT_SOURCE_MOUSE)));
4030 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4031 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4032 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4033 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4034
4035 // pilfer the motion, retaining the gesture on the spy window.
4036 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4037 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4038 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4039
4040 // Touch UP on the window
4041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004042 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004043 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4044 AINPUT_SOURCE_TOUCHSCREEN)
4045 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004046 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004047 .build()));
4048 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4049 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4050
4051 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4052 // to send a new gesture. It should again go to both windows (spy and the window below), just
4053 // like the first gesture did, before pilfering. The window configuration has not changed.
4054
4055 // One more tap - DOWN
4056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004057 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004058 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4059 AINPUT_SOURCE_TOUCHSCREEN)
4060 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004061 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004062 .build()));
4063 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4064 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4065 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4066 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4067
4068 // Touch UP on the window
4069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004070 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004071 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4072 AINPUT_SOURCE_TOUCHSCREEN)
4073 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004074 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004075 .build()));
4076 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4077 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4078 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4079 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4080
4081 window->assertNoEvents();
4082 spyWindow->assertNoEvents();
4083}
4084
Garfield Tandf26e862020-07-01 20:18:19 -07004085// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4086// directly in this test.
4087TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004089 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004090 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004091 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004092
4093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4094
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004095 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004096
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004098 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004099 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4100 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004101 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004102 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004103 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004104 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004106 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004107 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4108 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004109 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004110 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004111 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004113
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004116 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4117 AINPUT_SOURCE_MOUSE)
4118 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4119 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004121 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004122 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004123
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004125 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004126 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4127 AINPUT_SOURCE_MOUSE)
4128 .buttonState(0)
4129 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004131 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004132 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004133
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004135 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004136 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4137 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004139 .build()));
4140 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4141
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004142 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4143 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4144 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004145 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004146 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4147 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004148 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004149 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004150 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004151}
4152
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004153/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004154 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4155 * is generated.
4156 */
4157TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4159 sp<FakeWindowHandle> window =
4160 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4161 window->setFrame(Rect(0, 0, 1200, 800));
4162
4163 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004166
4167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004168 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004169 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4170 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004171 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004172 .build()));
4173 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4174
4175 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004176 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004177 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4178}
4179
4180/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004181 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4182 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004183TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4184 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4185 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4187 sp<FakeWindowHandle> window =
4188 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4189 window->setFrame(Rect(0, 0, 1200, 800));
4190
4191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4192
4193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4194
4195 MotionEventBuilder hoverEnterBuilder =
4196 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4197 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4198 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4200 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4202 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4203 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4204 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4205}
4206
4207/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004208 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4209 */
4210TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4212 sp<FakeWindowHandle> window =
4213 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4214 window->setFrame(Rect(0, 0, 100, 100));
4215
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004216 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004217
4218 const int32_t mouseDeviceId = 7;
4219 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004220
4221 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4223 .deviceId(mouseDeviceId)
4224 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4225 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004226 window->consumeMotionEvent(
4227 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4228
4229 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4231 .deviceId(touchDeviceId)
4232 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4233 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004234
4235 window->consumeMotionEvent(
4236 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4238}
4239
4240/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004241 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004242 * The tap causes a HOVER_EXIT event to be generated because the current event
4243 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004244 */
4245TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4247 sp<FakeWindowHandle> window =
4248 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4249 window->setFrame(Rect(0, 0, 100, 100));
4250
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004251 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004252 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4254 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004255 ASSERT_NO_FATAL_FAILURE(
4256 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4257 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004258
4259 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4261 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4262 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004263 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004264 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4265 WithSource(AINPUT_SOURCE_MOUSE))));
4266
4267 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004268 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4269 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4270
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4273 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004274 ASSERT_NO_FATAL_FAILURE(
4275 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4276 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4277}
4278
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004279TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4281 sp<FakeWindowHandle> windowDefaultDisplay =
4282 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4283 ADISPLAY_ID_DEFAULT);
4284 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4285 sp<FakeWindowHandle> windowSecondDisplay =
4286 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4287 SECOND_DISPLAY_ID);
4288 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4289
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004290 mDispatcher->onWindowInfosChanged(
4291 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004292
4293 // Set cursor position in window in default display and check that hover enter and move
4294 // events are generated.
4295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004296 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004297 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4298 AINPUT_SOURCE_MOUSE)
4299 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004300 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004301 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004302 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004303
4304 // Remove all windows in secondary display and check that no event happens on window in
4305 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004306 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4307
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004308 windowDefaultDisplay->assertNoEvents();
4309
4310 // Move cursor position in window in default display and check that only hover move
4311 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004312 mDispatcher->onWindowInfosChanged(
4313 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004315 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004316 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4317 AINPUT_SOURCE_MOUSE)
4318 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004320 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004321 windowDefaultDisplay->consumeMotionEvent(
4322 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4323 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004324 windowDefaultDisplay->assertNoEvents();
4325}
4326
Garfield Tan00f511d2019-06-12 16:55:40 -07004327TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004329
4330 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004332 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004333 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004334 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004335 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004336
4337 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4338
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004339 mDispatcher->onWindowInfosChanged(
4340 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004341
4342 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4343 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004345 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004346 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004347 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004348 windowRight->assertNoEvents();
4349}
4350
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004351TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004353 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4354 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004355 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004356
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004357 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004358 setFocusedWindow(window);
4359
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004360 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004361
Prabir Pradhan678438e2023-04-13 19:32:51 +00004362 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004363
4364 // Window should receive key down event.
4365 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4366
4367 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4368 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004369 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004370 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004371}
4372
4373TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004375 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4376 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004377
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004378 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004379
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4381 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004382
4383 // Window should receive motion down event.
4384 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4385
4386 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4387 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004388 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004389 window->consumeMotionEvent(
4390 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004391}
4392
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004393TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4396 "Fake Window", ADISPLAY_ID_DEFAULT);
4397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004398 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004399
4400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4402 .build());
4403
4404 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4405
4406 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4407 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4408 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4409
4410 // After the device has been reset, a new hovering stream can be sent to the window
4411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4412 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4413 .build());
4414 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4415}
4416
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004417TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004419 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4420 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004421 window->setFocusable(true);
4422
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004423 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004424 setFocusedWindow(window);
4425
4426 window->consumeFocusEvent(true);
4427
Prabir Pradhan678438e2023-04-13 19:32:51 +00004428 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004429 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4430 const nsecs_t injectTime = keyArgs.eventTime;
4431 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004432 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004433 // The dispatching time should be always greater than or equal to intercept key timeout.
4434 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4435 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4436 std::chrono::nanoseconds(interceptKeyTimeout).count());
4437}
4438
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004439/**
4440 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4441 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004442TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004444 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4445 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004446 window->setFocusable(true);
4447
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004448 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004449 setFocusedWindow(window);
4450
4451 window->consumeFocusEvent(true);
4452
Prabir Pradhan678438e2023-04-13 19:32:51 +00004453 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004454 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004455
4456 // Set a value that's significantly larger than the default consumption timeout. If the
4457 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4458 mFakePolicy->setInterceptKeyTimeout(600ms);
4459 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4460 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004461 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4462}
4463
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004464/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004465 * Two windows. First is a regular window. Second does not overlap with the first, and has
4466 * WATCH_OUTSIDE_TOUCH.
4467 * Both windows are owned by the same UID.
4468 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4469 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4470 */
4471TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004473 sp<FakeWindowHandle> window =
4474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004475 window->setFrame(Rect{0, 0, 100, 100});
4476
4477 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004478 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004479 ADISPLAY_ID_DEFAULT);
4480 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4481 outsideWindow->setWatchOutsideTouch(true);
4482 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004483 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004484
4485 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004486 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4487 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4488 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004489 window->consumeMotionDown();
4490 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4491 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4492 outsideWindow->consumeMotionEvent(
4493 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004494
4495 // Ensure outsideWindow doesn't get any more events for the gesture.
4496 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4497 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4498 window->consumeMotionMove();
4499 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004500}
4501
4502/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004503 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4504 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4505 * ACTION_OUTSIDE event is sent per gesture.
4506 */
4507TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4508 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004510 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4511 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004512 window->setWatchOutsideTouch(true);
4513 window->setFrame(Rect{0, 0, 100, 100});
4514 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004515 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4516 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004517 secondWindow->setFrame(Rect{100, 100, 200, 200});
4518 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004519 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4520 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004521 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004522 mDispatcher->onWindowInfosChanged(
4523 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004524
4525 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4528 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004529 window->assertNoEvents();
4530 secondWindow->assertNoEvents();
4531
4532 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4533 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004534 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4535 ADISPLAY_ID_DEFAULT,
4536 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004537 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4538 window->consumeMotionEvent(
4539 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004540 secondWindow->consumeMotionDown();
4541 thirdWindow->assertNoEvents();
4542
4543 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4544 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004545 mDispatcher->notifyMotion(
4546 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4547 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004548 window->assertNoEvents();
4549 secondWindow->consumeMotionMove();
4550 thirdWindow->consumeMotionDown();
4551}
4552
Prabir Pradhan814fe082022-07-22 20:22:18 +00004553TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004555 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4556 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004557 window->setFocusable(true);
4558
Patrick Williamsd828f302023-04-28 17:52:08 -05004559 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004560 setFocusedWindow(window);
4561
4562 window->consumeFocusEvent(true);
4563
Prabir Pradhan678438e2023-04-13 19:32:51 +00004564 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4565 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4566 mDispatcher->notifyKey(keyDown);
4567 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004568
4569 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4570 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4571
4572 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004573 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004574
4575 window->consumeFocusEvent(false);
4576
Prabir Pradhan678438e2023-04-13 19:32:51 +00004577 mDispatcher->notifyKey(keyDown);
4578 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004579 window->assertNoEvents();
4580}
4581
Arthur Hung96483742022-11-15 03:30:48 +00004582TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4585 "Fake Window", ADISPLAY_ID_DEFAULT);
4586 // Ensure window is non-split and have some transform.
4587 window->setPreventSplitting(true);
4588 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004589 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004590
4591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004593 {50, 50}))
4594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4595 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4596
4597 const MotionEvent secondFingerDownEvent =
4598 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4599 .displayId(ADISPLAY_ID_DEFAULT)
4600 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004601 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4602 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004603 .build();
4604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004605 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004606 InputEventInjectionSync::WAIT_FOR_RESULT))
4607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4608
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004609 const MotionEvent& event = window->consumeMotionEvent();
4610 EXPECT_EQ(POINTER_1_DOWN, event.getAction());
4611 EXPECT_EQ(70, event.getX(0)); // 50 + 20
4612 EXPECT_EQ(90, event.getY(0)); // 50 + 40
4613 EXPECT_EQ(-10, event.getX(1)); // -30 + 20
4614 EXPECT_EQ(-10, event.getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004615}
4616
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004617/**
4618 * Two windows: a splittable and a non-splittable.
4619 * The non-splittable window shouldn't receive any "incomplete" gestures.
4620 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4621 * The second pointer should be dropped because the initial window is splittable, so it won't get
4622 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4623 * "incomplete" gestures.
4624 */
4625TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4627 sp<FakeWindowHandle> leftWindow =
4628 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4629 ADISPLAY_ID_DEFAULT);
4630 leftWindow->setPreventSplitting(false);
4631 leftWindow->setFrame(Rect(0, 0, 100, 100));
4632 sp<FakeWindowHandle> rightWindow =
4633 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4634 ADISPLAY_ID_DEFAULT);
4635 rightWindow->setPreventSplitting(true);
4636 rightWindow->setFrame(Rect(100, 100, 200, 200));
4637 mDispatcher->onWindowInfosChanged(
4638 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4639
4640 // Touch down on left, splittable window
4641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4642 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4643 .build());
4644 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4645
4646 mDispatcher->notifyMotion(
4647 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4648 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4649 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4650 .build());
4651 leftWindow->assertNoEvents();
4652 rightWindow->assertNoEvents();
4653}
4654
Harry Cuttsb166c002023-05-09 13:06:05 +00004655TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4657 sp<FakeWindowHandle> window =
4658 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4659 window->setFrame(Rect(0, 0, 400, 400));
4660 sp<FakeWindowHandle> trustedOverlay =
4661 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4662 ADISPLAY_ID_DEFAULT);
4663 trustedOverlay->setSpy(true);
4664 trustedOverlay->setTrustedOverlay(true);
4665
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004666 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004667
4668 // Start a three-finger touchpad swipe
4669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4670 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4671 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4672 .build());
4673 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4674 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4675 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4676 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4677 .build());
4678 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4679 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4680 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4681 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4682 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4683 .build());
4684
4685 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4686 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4687 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4688
4689 // Move the swipe a bit
4690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4691 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4692 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4693 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4694 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4695 .build());
4696
4697 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4698
4699 // End the swipe
4700 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4701 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4702 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4703 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4704 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4705 .build());
4706 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4707 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4708 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4709 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4710 .build());
4711 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4712 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4713 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4714 .build());
4715
4716 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4717 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4718 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4719
4720 window->assertNoEvents();
4721}
4722
4723TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4725 sp<FakeWindowHandle> window =
4726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4727 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004729
4730 // Start a three-finger touchpad swipe
4731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4732 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4733 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4734 .build());
4735 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4736 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4737 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4738 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4739 .build());
4740 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4741 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4742 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4743 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4744 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4745 .build());
4746
4747 // Move the swipe a bit
4748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4749 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4750 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4751 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4752 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4753 .build());
4754
4755 // End the swipe
4756 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4757 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4758 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4759 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4760 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4761 .build());
4762 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4764 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4765 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4766 .build());
4767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4768 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4769 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4770 .build());
4771
4772 window->assertNoEvents();
4773}
4774
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004775/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004776 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4777 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004778 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004779 */
4780TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4782 sp<FakeWindowHandle> window =
4783 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4784 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004785 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004786
4787 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4789 .downTime(baseTime + 10)
4790 .eventTime(baseTime + 10)
4791 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4792 .build());
4793
4794 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4795
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004796 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004797 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004798
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004800
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004801 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4802 .downTime(baseTime + 10)
4803 .eventTime(baseTime + 30)
4804 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4805 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4806 .build());
4807
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004808 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4809
4810 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004811 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4812 .downTime(baseTime + 10)
4813 .eventTime(baseTime + 40)
4814 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4815 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4816 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004817
4818 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4819
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4821 .downTime(baseTime + 10)
4822 .eventTime(baseTime + 50)
4823 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4824 .build());
4825
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004826 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4827
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004828 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4829 .downTime(baseTime + 60)
4830 .eventTime(baseTime + 60)
4831 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4832 .build());
4833
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004834 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004835}
4836
4837/**
Hu Guo771a7692023-09-17 20:51:08 +08004838 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4839 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4840 * its coordinates should be converted by the transform of the windows of target screen.
4841 */
4842TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4843 // This case will create a window and a spy window on the default display and mirror
4844 // window on the second display. cancel event is sent through spy window pilferPointers
4845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4846
4847 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4848 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4849 spyWindowDefaultDisplay->setTrustedOverlay(true);
4850 spyWindowDefaultDisplay->setSpy(true);
4851
4852 sp<FakeWindowHandle> windowDefaultDisplay =
4853 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4854 ADISPLAY_ID_DEFAULT);
4855 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4856
4857 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4858 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4859
4860 // Add the windows to the dispatcher
4861 mDispatcher->onWindowInfosChanged(
4862 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4863 *windowSecondDisplay->getInfo()},
4864 {},
4865 0,
4866 0});
4867
4868 // Send down to ADISPLAY_ID_DEFAULT
4869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4870 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4871 {100, 100}))
4872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4873
4874 spyWindowDefaultDisplay->consumeMotionDown();
4875 windowDefaultDisplay->consumeMotionDown();
4876
4877 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4878
4879 // windowDefaultDisplay gets cancel
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004880 const MotionEvent& event = windowDefaultDisplay->consumeMotionEvent();
4881 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004882
4883 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4884 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4885 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4886 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004887 EXPECT_EQ(100, event.getX(0));
4888 EXPECT_EQ(100, event.getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004889}
4890
4891/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004892 * Ensure the correct coordinate spaces are used by InputDispatcher.
4893 *
4894 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4895 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4896 * space.
4897 */
4898class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4899public:
4900 void SetUp() override {
4901 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004902 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004903 }
4904
4905 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4906 gui::DisplayInfo info;
4907 info.displayId = displayId;
4908 info.transform = transform;
4909 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004910 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004911 }
4912
4913 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4914 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004915 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004916 }
4917
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004918 void removeAllWindowsAndDisplays() {
4919 mDisplayInfos.clear();
4920 mWindowInfos.clear();
4921 }
4922
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004923 // Set up a test scenario where the display has a scaled projection and there are two windows
4924 // on the display.
4925 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4926 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4927 // respectively.
4928 ui::Transform displayTransform;
4929 displayTransform.set(2, 0, 0, 4);
4930 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4931
4932 std::shared_ptr<FakeApplicationHandle> application =
4933 std::make_shared<FakeApplicationHandle>();
4934
4935 // Add two windows to the display. Their frames are represented in the display space.
4936 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004937 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4938 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004939 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4940 addWindow(firstWindow);
4941
4942 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004943 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4944 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004945 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4946 addWindow(secondWindow);
4947 return {std::move(firstWindow), std::move(secondWindow)};
4948 }
4949
4950private:
4951 std::vector<gui::DisplayInfo> mDisplayInfos;
4952 std::vector<gui::WindowInfo> mWindowInfos;
4953};
4954
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004955TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004956 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4957 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004958 // selected so that if the hit test was performed with the point and the bounds being in
4959 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004960 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4961 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4962 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004963
4964 firstWindow->consumeMotionDown();
4965 secondWindow->assertNoEvents();
4966}
4967
4968// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4969// the event should be treated as being in the logical display space.
4970TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4971 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4972 // Send down to the first window. The point is represented in the logical display space. The
4973 // point is selected so that if the hit test was done in logical display space, then it would
4974 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004976 PointF{75 * 2, 55 * 4});
4977
4978 firstWindow->consumeMotionDown();
4979 secondWindow->assertNoEvents();
4980}
4981
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004982// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4983// event should be treated as being in the logical display space.
4984TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4985 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4986
4987 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4988 ui::Transform injectedEventTransform;
4989 injectedEventTransform.set(matrix);
4990 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4991 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4992
4993 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4994 .displayId(ADISPLAY_ID_DEFAULT)
4995 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004996 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004997 .x(untransformedPoint.x)
4998 .y(untransformedPoint.y))
4999 .build();
5000 event.transform(matrix);
5001
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005002 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005003 InputEventInjectionSync::WAIT_FOR_RESULT);
5004
5005 firstWindow->consumeMotionDown();
5006 secondWindow->assertNoEvents();
5007}
5008
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005009TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5010 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5011
5012 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005013 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5015 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005016
5017 firstWindow->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005018 const MotionEvent& event = secondWindow->consumeMotionEvent();
5019 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event.getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005020
5021 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005022 EXPECT_EQ(300, event.getRawX(0));
5023 EXPECT_EQ(880, event.getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005024
5025 // Ensure that the x and y values are in the window's coordinate space.
5026 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5027 // the logical display space. This will be the origin of the window space.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005028 EXPECT_EQ(100, event.getX(0));
5029 EXPECT_EQ(80, event.getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005030}
5031
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005032TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5033 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5034 // The monitor will always receive events in the logical display's coordinate space, because
5035 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005036 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005037
5038 // Send down to the first window.
5039 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5040 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5041 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5042 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5043
5044 // Second pointer goes down on second window.
5045 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5046 ADISPLAY_ID_DEFAULT,
5047 {PointF{50, 100}, PointF{150, 220}}));
5048 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5049 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5050 {1, PointF{300, 880}}};
5051 monitor.consumeMotionEvent(
5052 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5053
5054 mDispatcher->cancelCurrentTouch();
5055
5056 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5057 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5058 monitor.consumeMotionEvent(
5059 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5060}
5061
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005062TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5063 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5064
5065 // Send down to the first window.
5066 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5067 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5068 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5069
5070 // The pointer is transferred to the second window, and the second window receives it in the
5071 // correct coordinate space.
5072 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5073 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5074 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5075}
5076
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005077TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5078 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5079
5080 // Send hover move to the second window, and ensure it shows up as hover enter.
5081 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5082 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5083 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5084 WithCoords(100, 80), WithRawCoords(300, 880)));
5085
5086 // Touch down at the same location and ensure a hover exit is synthesized.
5087 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5088 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5089 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5090 WithRawCoords(300, 880)));
5091 secondWindow->consumeMotionEvent(
5092 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5093 secondWindow->assertNoEvents();
5094 firstWindow->assertNoEvents();
5095}
5096
Prabir Pradhan453ae732023-10-13 14:30:14 +00005097// Same as above, but while the window is being mirrored.
5098TEST_F(InputDispatcherDisplayProjectionTest,
5099 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5100 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5101
5102 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5103 ui::Transform secondDisplayTransform;
5104 secondDisplayTransform.set(matrix);
5105 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5106
5107 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5108 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5109 addWindow(secondWindowClone);
5110
5111 // Send hover move to the second window, and ensure it shows up as hover enter.
5112 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5113 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5114 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5115 WithCoords(100, 80), WithRawCoords(300, 880)));
5116
5117 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5118 // display.
5119 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5120 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5121 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5122 WithRawCoords(300, 880)));
5123 secondWindow->consumeMotionEvent(
5124 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5125 secondWindow->assertNoEvents();
5126 firstWindow->assertNoEvents();
5127}
5128
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005129TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5130 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5131
5132 // Send hover enter to second window
5133 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5134 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5135 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5136 WithCoords(100, 80), WithRawCoords(300, 880)));
5137
5138 mDispatcher->cancelCurrentTouch();
5139
5140 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5141 WithRawCoords(300, 880)));
5142 secondWindow->assertNoEvents();
5143 firstWindow->assertNoEvents();
5144}
5145
Prabir Pradhan453ae732023-10-13 14:30:14 +00005146// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005147TEST_F(InputDispatcherDisplayProjectionTest,
5148 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5149 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5150
5151 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5152 ui::Transform secondDisplayTransform;
5153 secondDisplayTransform.set(matrix);
5154 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5155
5156 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5157 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5158 addWindow(secondWindowClone);
5159
5160 // Send hover enter to second window
5161 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5162 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5163 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5164 WithCoords(100, 80), WithRawCoords(300, 880),
5165 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5166
5167 mDispatcher->cancelCurrentTouch();
5168
5169 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5170 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5171 WithRawCoords(300, 880),
5172 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5173 secondWindow->assertNoEvents();
5174 firstWindow->assertNoEvents();
5175}
5176
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005177/** Ensure consistent behavior of InputDispatcher in all orientations. */
5178class InputDispatcherDisplayOrientationFixture
5179 : public InputDispatcherDisplayProjectionTest,
5180 public ::testing::WithParamInterface<ui::Rotation> {};
5181
5182// This test verifies the touchable region of a window for all rotations of the display by tapping
5183// in different locations on the display, specifically points close to the four corners of a
5184// window.
5185TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5186 constexpr static int32_t displayWidth = 400;
5187 constexpr static int32_t displayHeight = 800;
5188
5189 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5190
5191 const auto rotation = GetParam();
5192
5193 // Set up the display with the specified rotation.
5194 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5195 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5196 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5197 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5198 logicalDisplayWidth, logicalDisplayHeight);
5199 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5200
5201 // Create a window with its bounds determined in the logical display.
5202 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5203 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5204 sp<FakeWindowHandle> window =
5205 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5206 window->setFrame(frameInDisplay, displayTransform);
5207 addWindow(window);
5208
5209 // The following points in logical display space should be inside the window.
5210 static const std::array<vec2, 4> insidePoints{
5211 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5212 for (const auto pointInsideWindow : insidePoints) {
5213 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5214 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005215 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5216 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5217 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005218 window->consumeMotionDown();
5219
Prabir Pradhan678438e2023-04-13 19:32:51 +00005220 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5221 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5222 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005223 window->consumeMotionUp();
5224 }
5225
5226 // The following points in logical display space should be outside the window.
5227 static const std::array<vec2, 5> outsidePoints{
5228 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5229 for (const auto pointOutsideWindow : outsidePoints) {
5230 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5231 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005232 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5233 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5234 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005235
Prabir Pradhan678438e2023-04-13 19:32:51 +00005236 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5237 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5238 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005239 }
5240 window->assertNoEvents();
5241}
5242
5243// Run the precision tests for all rotations.
5244INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5245 InputDispatcherDisplayOrientationFixture,
5246 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5247 ui::ROTATION_270),
5248 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5249 return ftl::enum_string(testParamInfo.param);
5250 });
5251
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005252using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5253 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005254
5255class TransferTouchFixture : public InputDispatcherTest,
5256 public ::testing::WithParamInterface<TransferFunction> {};
5257
5258TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005259 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005260
5261 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005262 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005263 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5264 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005265 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005266 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005267 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5268 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005269 sp<FakeWindowHandle> wallpaper =
5270 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5271 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005272 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005273 mDispatcher->onWindowInfosChanged(
5274 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005275
5276 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005277 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5278 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005279
Svet Ganov5d3bc372020-01-26 23:11:07 -08005280 // Only the first window should get the down event
5281 firstWindow->consumeMotionDown();
5282 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005284
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005285 // Transfer touch to the second window
5286 TransferFunction f = GetParam();
5287 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5288 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005289 // The first window gets cancel and the second gets down
5290 firstWindow->consumeMotionCancel();
5291 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005292 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005293
5294 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5296 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005297 // The first window gets no events and the second gets up
5298 firstWindow->assertNoEvents();
5299 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005300 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005301}
5302
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005303/**
5304 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5305 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5306 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5307 * natural to the user.
5308 * In this test, we are sending a pointer to both spy window and first window. We then try to
5309 * transfer touch to the second window. The dispatcher should identify the first window as the
5310 * one that should lose the gesture, and therefore the action should be to move the gesture from
5311 * the first window to the second.
5312 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5313 * the other API, as well.
5314 */
5315TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5317
5318 // Create a couple of windows + a spy window
5319 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005320 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005321 spyWindow->setTrustedOverlay(true);
5322 spyWindow->setSpy(true);
5323 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005324 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005325 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005327
5328 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005329 mDispatcher->onWindowInfosChanged(
5330 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005331
5332 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005333 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5334 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005335 // Only the first window and spy should get the down event
5336 spyWindow->consumeMotionDown();
5337 firstWindow->consumeMotionDown();
5338
5339 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5340 // if f === 'transferTouch'.
5341 TransferFunction f = GetParam();
5342 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5343 ASSERT_TRUE(success);
5344 // The first window gets cancel and the second gets down
5345 firstWindow->consumeMotionCancel();
5346 secondWindow->consumeMotionDown();
5347
5348 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5350 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005351 // The first window gets no events and the second+spy get up
5352 firstWindow->assertNoEvents();
5353 spyWindow->consumeMotionUp();
5354 secondWindow->consumeMotionUp();
5355}
5356
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005357TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005359
5360 PointF touchPoint = {10, 10};
5361
5362 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005363 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005364 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5365 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005366 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005367 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005368 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5369 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005370 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371
5372 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005373 mDispatcher->onWindowInfosChanged(
5374 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005375
5376 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005377 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5378 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5379 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005380 // Only the first window should get the down event
5381 firstWindow->consumeMotionDown();
5382 secondWindow->assertNoEvents();
5383
5384 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005385 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5386 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005387 // Only the first window should get the pointer down event
5388 firstWindow->consumeMotionPointerDown(1);
5389 secondWindow->assertNoEvents();
5390
5391 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005392 TransferFunction f = GetParam();
5393 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5394 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005395 // The first window gets cancel and the second gets down and pointer down
5396 firstWindow->consumeMotionCancel();
5397 secondWindow->consumeMotionDown();
5398 secondWindow->consumeMotionPointerDown(1);
5399
5400 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005401 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5402 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005403 // The first window gets nothing and the second gets pointer up
5404 firstWindow->assertNoEvents();
5405 secondWindow->consumeMotionPointerUp(1);
5406
5407 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5409 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005410 // The first window gets nothing and the second gets up
5411 firstWindow->assertNoEvents();
5412 secondWindow->consumeMotionUp();
5413}
5414
Arthur Hungc539dbb2022-12-08 07:45:36 +00005415TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5417
5418 // Create a couple of windows
5419 sp<FakeWindowHandle> firstWindow =
5420 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5421 ADISPLAY_ID_DEFAULT);
5422 firstWindow->setDupTouchToWallpaper(true);
5423 sp<FakeWindowHandle> secondWindow =
5424 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5425 ADISPLAY_ID_DEFAULT);
5426 secondWindow->setDupTouchToWallpaper(true);
5427
5428 sp<FakeWindowHandle> wallpaper1 =
5429 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5430 wallpaper1->setIsWallpaper(true);
5431
5432 sp<FakeWindowHandle> wallpaper2 =
5433 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5434 wallpaper2->setIsWallpaper(true);
5435 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005436 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5437 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5438 {},
5439 0,
5440 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005441
5442 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5444 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005445
5446 // Only the first window should get the down event
5447 firstWindow->consumeMotionDown();
5448 secondWindow->assertNoEvents();
5449 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5450 wallpaper2->assertNoEvents();
5451
5452 // Transfer touch focus to the second window
5453 TransferFunction f = GetParam();
5454 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5455 ASSERT_TRUE(success);
5456
5457 // The first window gets cancel and the second gets down
5458 firstWindow->consumeMotionCancel();
5459 secondWindow->consumeMotionDown();
5460 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5461 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5462
5463 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5465 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005466 // The first window gets no events and the second gets up
5467 firstWindow->assertNoEvents();
5468 secondWindow->consumeMotionUp();
5469 wallpaper1->assertNoEvents();
5470 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5471}
5472
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005473// For the cases of single pointer touch and two pointers non-split touch, the api's
5474// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5475// for the case where there are multiple pointers split across several windows.
5476INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5477 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005478 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5479 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005480 return dispatcher->transferTouch(destChannelToken,
5481 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005482 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005483 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5484 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005485 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005486 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005487 }));
5488
Svet Ganov5d3bc372020-01-26 23:11:07 -08005489TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005491
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005492 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005493 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5494 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005495 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005496
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005497 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005498 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5499 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005500 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005501
5502 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005503 mDispatcher->onWindowInfosChanged(
5504 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005505
5506 PointF pointInFirst = {300, 200};
5507 PointF pointInSecond = {300, 600};
5508
5509 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005510 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5511 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5512 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005513 // Only the first window should get the down event
5514 firstWindow->consumeMotionDown();
5515 secondWindow->assertNoEvents();
5516
5517 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005518 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5519 ADISPLAY_ID_DEFAULT,
5520 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005521 // The first window gets a move and the second a down
5522 firstWindow->consumeMotionMove();
5523 secondWindow->consumeMotionDown();
5524
5525 // Transfer touch focus to the second window
5526 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5527 // The first window gets cancel and the new gets pointer down (it already saw down)
5528 firstWindow->consumeMotionCancel();
5529 secondWindow->consumeMotionPointerDown(1);
5530
5531 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005532 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5533 ADISPLAY_ID_DEFAULT,
5534 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005535 // The first window gets nothing and the second gets pointer up
5536 firstWindow->assertNoEvents();
5537 secondWindow->consumeMotionPointerUp(1);
5538
5539 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005540 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5541 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005542 // The first window gets nothing and the second gets up
5543 firstWindow->assertNoEvents();
5544 secondWindow->consumeMotionUp();
5545}
5546
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005547// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5548// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5549// touch is not supported, so the touch should continue on those windows and the transferred-to
5550// window should get nothing.
5551TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5553
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005554 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005555 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5556 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005557 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005558
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005559 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005560 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5561 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005562 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005563
5564 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005565 mDispatcher->onWindowInfosChanged(
5566 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005567
5568 PointF pointInFirst = {300, 200};
5569 PointF pointInSecond = {300, 600};
5570
5571 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005572 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5573 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5574 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005575 // Only the first window should get the down event
5576 firstWindow->consumeMotionDown();
5577 secondWindow->assertNoEvents();
5578
5579 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005580 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5581 ADISPLAY_ID_DEFAULT,
5582 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005583 // The first window gets a move and the second a down
5584 firstWindow->consumeMotionMove();
5585 secondWindow->consumeMotionDown();
5586
5587 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005588 const bool transferred =
5589 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005590 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5591 ASSERT_FALSE(transferred);
5592 firstWindow->assertNoEvents();
5593 secondWindow->assertNoEvents();
5594
5595 // The rest of the dispatch should proceed as normal
5596 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005597 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5598 ADISPLAY_ID_DEFAULT,
5599 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005600 // The first window gets MOVE and the second gets pointer up
5601 firstWindow->consumeMotionMove();
5602 secondWindow->consumeMotionUp();
5603
5604 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005605 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5606 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005607 // The first window gets nothing and the second gets up
5608 firstWindow->consumeMotionUp();
5609 secondWindow->assertNoEvents();
5610}
5611
Arthur Hungabbb9d82021-09-01 14:52:30 +00005612// This case will create two windows and one mirrored window on the default display and mirror
5613// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5614// the windows info of second display before default display.
5615TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5617 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005618 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005619 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005620 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005621 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005622 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005623
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005624 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005625 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005626
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005627 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005628 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005629
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005630 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005631 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005632
5633 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005634 mDispatcher->onWindowInfosChanged(
5635 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5636 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5637 *secondWindowInPrimary->getInfo()},
5638 {},
5639 0,
5640 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005641
5642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005643 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005644 {50, 50}))
5645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5646
5647 // Window should receive motion event.
5648 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5649
5650 // Transfer touch focus
5651 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5652 secondWindowInPrimary->getToken()));
5653 // The first window gets cancel.
5654 firstWindowInPrimary->consumeMotionCancel();
5655 secondWindowInPrimary->consumeMotionDown();
5656
5657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005659 ADISPLAY_ID_DEFAULT, {150, 50}))
5660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5661 firstWindowInPrimary->assertNoEvents();
5662 secondWindowInPrimary->consumeMotionMove();
5663
5664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005665 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005666 {150, 50}))
5667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5668 firstWindowInPrimary->assertNoEvents();
5669 secondWindowInPrimary->consumeMotionUp();
5670}
5671
5672// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5673// 'transferTouch' api.
5674TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5676 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005677 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005678 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005679 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005680 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005681 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005682
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005683 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005684 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005685
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005686 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005687 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005688
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005689 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005690 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005691
5692 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005693 mDispatcher->onWindowInfosChanged(
5694 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5695 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5696 *secondWindowInPrimary->getInfo()},
5697 {},
5698 0,
5699 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005700
5701 // Touch on second display.
5702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005703 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5704 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5706
5707 // Window should receive motion event.
5708 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5709
5710 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005711 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005712
5713 // The first window gets cancel.
5714 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5715 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5716
5717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005718 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005719 SECOND_DISPLAY_ID, {150, 50}))
5720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5721 firstWindowInPrimary->assertNoEvents();
5722 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5723
5724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005725 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5727 firstWindowInPrimary->assertNoEvents();
5728 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5729}
5730
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005731TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5734 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005735
Vishnu Nair47074b82020-08-14 11:54:47 -07005736 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005738 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005739
5740 window->consumeFocusEvent(true);
5741
Prabir Pradhan678438e2023-04-13 19:32:51 +00005742 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005743
5744 // Window should receive key down event.
5745 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005746
5747 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005748 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005749 mFakePolicy->assertUserActivityPoked();
5750}
5751
5752TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5755 "Fake Window", ADISPLAY_ID_DEFAULT);
5756
5757 window->setDisableUserActivity(true);
5758 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005760 setFocusedWindow(window);
5761
5762 window->consumeFocusEvent(true);
5763
5764 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5765
5766 // Window should receive key down event.
5767 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5768
5769 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005770 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005771 mFakePolicy->assertUserActivityNotPoked();
5772}
5773
5774TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5776 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5777 "Fake Window", ADISPLAY_ID_DEFAULT);
5778
5779 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005781 setFocusedWindow(window);
5782
5783 window->consumeFocusEvent(true);
5784
5785 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5786 mDispatcher->waitForIdle();
5787
5788 // System key is not passed down
5789 window->assertNoEvents();
5790
5791 // Should have poked user activity
5792 mFakePolicy->assertUserActivityPoked();
5793}
5794
5795TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5798 "Fake Window", ADISPLAY_ID_DEFAULT);
5799
5800 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005802 setFocusedWindow(window);
5803
5804 window->consumeFocusEvent(true);
5805
5806 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5807 mDispatcher->waitForIdle();
5808
5809 // System key is not passed down
5810 window->assertNoEvents();
5811
5812 // Should have poked user activity
5813 mFakePolicy->assertUserActivityPoked();
5814}
5815
5816TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5818 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5819 "Fake Window", ADISPLAY_ID_DEFAULT);
5820
5821 window->setDisableUserActivity(true);
5822 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005824 setFocusedWindow(window);
5825
5826 window->consumeFocusEvent(true);
5827
5828 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5829 mDispatcher->waitForIdle();
5830
5831 // System key is not passed down
5832 window->assertNoEvents();
5833
5834 // Should have poked user activity
5835 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005836}
5837
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005838TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5840 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5841 "Fake Window", ADISPLAY_ID_DEFAULT);
5842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005844
5845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005846 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005847 ADISPLAY_ID_DEFAULT, {100, 100}))
5848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5849
5850 window->consumeMotionEvent(
5851 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5852
5853 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005854 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005855 mFakePolicy->assertUserActivityPoked();
5856}
5857
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005858TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005860 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5861 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005863 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005864
Prabir Pradhan678438e2023-04-13 19:32:51 +00005865 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005866 mDispatcher->waitForIdle();
5867
5868 window->assertNoEvents();
5869}
5870
5871// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5872TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5875 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005878
5879 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005880 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005881 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005882 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5883 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005884
5885 // Window should receive only the motion event
5886 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5887 window->assertNoEvents(); // Key event or focus event will not be received
5888}
5889
arthurhungea3f4fc2020-12-21 23:18:53 +08005890TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5892
arthurhungea3f4fc2020-12-21 23:18:53 +08005893 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005894 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5895 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005896 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005897
arthurhungea3f4fc2020-12-21 23:18:53 +08005898 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005899 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5900 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005901 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005902
5903 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005904 mDispatcher->onWindowInfosChanged(
5905 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005906
5907 PointF pointInFirst = {300, 200};
5908 PointF pointInSecond = {300, 600};
5909
5910 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005911 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5912 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5913 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005914 // Only the first window should get the down event
5915 firstWindow->consumeMotionDown();
5916 secondWindow->assertNoEvents();
5917
5918 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005919 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5920 ADISPLAY_ID_DEFAULT,
5921 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005922 // The first window gets a move and the second a down
5923 firstWindow->consumeMotionMove();
5924 secondWindow->consumeMotionDown();
5925
5926 // Send pointer cancel to the second window
5927 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005928 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005929 {pointInFirst, pointInSecond});
5930 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005931 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005932 // The first window gets move and the second gets cancel.
5933 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5934 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5935
5936 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005937 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5938 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005939 // The first window gets up and the second gets nothing.
5940 firstWindow->consumeMotionUp();
5941 secondWindow->assertNoEvents();
5942}
5943
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005944TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5946
5947 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005948 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005950 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5951 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5952 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5953
Harry Cutts33476232023-01-30 19:57:29 +00005954 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005955 window->assertNoEvents();
5956 mDispatcher->waitForIdle();
5957}
5958
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005959using InputDispatcherMonitorTest = InputDispatcherTest;
5960
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005961/**
5962 * Two entities that receive touch: A window, and a global monitor.
5963 * The touch goes to the window, and then the window disappears.
5964 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5965 * for the monitor, as well.
5966 * 1. foregroundWindow
5967 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5968 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005969TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005970 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5971 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005972 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005973
Prabir Pradhanfb549072023-10-05 19:17:36 +00005974 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005975
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005976 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005979 {100, 200}))
5980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5981
5982 // Both the foreground window and the global monitor should receive the touch down
5983 window->consumeMotionDown();
5984 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5985
5986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005987 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005988 ADISPLAY_ID_DEFAULT, {110, 200}))
5989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5990
5991 window->consumeMotionMove();
5992 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5993
5994 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005995 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005996 window->consumeMotionCancel();
5997 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5998
5999 // If more events come in, there will be no more foreground window to send them to. This will
6000 // cause a cancel for the monitor, as well.
6001 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006002 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006003 ADISPLAY_ID_DEFAULT, {120, 200}))
6004 << "Injection should fail because the window was removed";
6005 window->assertNoEvents();
6006 // Global monitor now gets the cancel
6007 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6008}
6009
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006010TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006012 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6013 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006014 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006015
Prabir Pradhanfb549072023-10-05 19:17:36 +00006016 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006017
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006019 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006021 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006022 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006023}
6024
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006025TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006026 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006027
Chris Yea209fde2020-07-22 13:54:51 -07006028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006029 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6030 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006031 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006034 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006036 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006037 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006038
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006039 // Pilfer pointers from the monitor.
6040 // This should not do anything and the window should continue to receive events.
6041 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006044 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006045 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006047
6048 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6049 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006050}
6051
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006052TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006054 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6055 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006056 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006057 window->setWindowOffset(20, 40);
6058 window->setWindowTransform(0, 1, -1, 0);
6059
Prabir Pradhanfb549072023-10-05 19:17:36 +00006060 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006061
6062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006063 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6065 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6066 MotionEvent* event = monitor.consumeMotion();
6067 // Even though window has transform, gesture monitor must not.
6068 ASSERT_EQ(ui::Transform(), event->getTransform());
6069}
6070
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006071TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006073 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006075 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006077 << "Injection should fail if there is a monitor, but no touchable window";
6078 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006079}
6080
chaviw81e2bb92019-12-18 15:03:51 -08006081TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006083 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6084 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006085
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006086 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006087
6088 NotifyMotionArgs motionArgs =
6089 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6090 ADISPLAY_ID_DEFAULT);
6091
Prabir Pradhan678438e2023-04-13 19:32:51 +00006092 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006093 // Window should receive motion down event.
6094 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6095
6096 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006097 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006098 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6099 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6100 motionArgs.pointerCoords[0].getX() - 10);
6101
Prabir Pradhan678438e2023-04-13 19:32:51 +00006102 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006103 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006104}
6105
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006106/**
6107 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6108 * the device default right away. In the test scenario, we check both the default value,
6109 * and the action of enabling / disabling.
6110 */
6111TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006113 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6114 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006115 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006116
6117 // Set focused application.
6118 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006119 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006120
6121 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006122 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006123 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006124 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006125
6126 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006127 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006128 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006129 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006130
6131 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006132 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006133 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006134 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006135 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006136 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006137 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006138 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006139
6140 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006141 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006143 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006144
6145 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006146 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006147 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006148 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006149 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006150 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006151 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006152 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006153
6154 window->assertNoEvents();
6155}
6156
Gang Wange9087892020-01-07 12:17:14 -05006157TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006159 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6160 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006161
6162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006163 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006166 setFocusedWindow(window);
6167
Harry Cutts33476232023-01-30 19:57:29 +00006168 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006169
Prabir Pradhan678438e2023-04-13 19:32:51 +00006170 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6171 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006172
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006173 const KeyEvent& event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006174
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006175 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Gang Wange9087892020-01-07 12:17:14 -05006176 ASSERT_NE(verified, nullptr);
6177 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6178
6179 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6180 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6181 ASSERT_EQ(keyArgs.source, verified->source);
6182 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6183
6184 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6185
6186 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006187 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006188 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006189 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6190 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6191 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6192 ASSERT_EQ(0, verifiedKey.repeatCount);
6193}
6194
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006195TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006197 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6198 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006199
6200 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6201
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006202 ui::Transform transform;
6203 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6204
6205 gui::DisplayInfo displayInfo;
6206 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6207 displayInfo.transform = transform;
6208
Patrick Williamsd828f302023-04-28 17:52:08 -05006209 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006210
Prabir Pradhan678438e2023-04-13 19:32:51 +00006211 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006212 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6213 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006214 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006215
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006216 const MotionEvent& event = window->consumeMotionEvent();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006217
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006218 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006219 ASSERT_NE(verified, nullptr);
6220 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6221
6222 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6223 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6224 EXPECT_EQ(motionArgs.source, verified->source);
6225 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6226
6227 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6228
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006229 const vec2 rawXY =
6230 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6231 motionArgs.pointerCoords[0].getXYValue());
6232 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6233 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006234 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006235 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006236 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006237 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6238 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6239}
6240
chaviw09c8d2d2020-08-24 15:48:26 -07006241/**
6242 * Ensure that separate calls to sign the same data are generating the same key.
6243 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6244 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6245 * tests.
6246 */
6247TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6248 KeyEvent event = getTestKeyEvent();
6249 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6250
6251 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6252 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6253 ASSERT_EQ(hmac1, hmac2);
6254}
6255
6256/**
6257 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6258 */
6259TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6260 KeyEvent event = getTestKeyEvent();
6261 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6262 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6263
6264 verifiedEvent.deviceId += 1;
6265 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6266
6267 verifiedEvent.source += 1;
6268 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6269
6270 verifiedEvent.eventTimeNanos += 1;
6271 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6272
6273 verifiedEvent.displayId += 1;
6274 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6275
6276 verifiedEvent.action += 1;
6277 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6278
6279 verifiedEvent.downTimeNanos += 1;
6280 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6281
6282 verifiedEvent.flags += 1;
6283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6284
6285 verifiedEvent.keyCode += 1;
6286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6287
6288 verifiedEvent.scanCode += 1;
6289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6290
6291 verifiedEvent.metaState += 1;
6292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6293
6294 verifiedEvent.repeatCount += 1;
6295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6296}
6297
Vishnu Nair958da932020-08-21 17:12:37 -07006298TEST_F(InputDispatcherTest, SetFocusedWindow) {
6299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6300 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006301 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006302 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006303 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006304 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6305
6306 // Top window is also focusable but is not granted focus.
6307 windowTop->setFocusable(true);
6308 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006309 mDispatcher->onWindowInfosChanged(
6310 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006311 setFocusedWindow(windowSecond);
6312
6313 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006315 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006316
6317 // Focused window should receive event.
6318 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6319 windowTop->assertNoEvents();
6320}
6321
6322TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6324 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006325 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006326 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6327
6328 window->setFocusable(true);
6329 // Release channel for window is no longer valid.
6330 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006331 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006332 setFocusedWindow(window);
6333
6334 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006335 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006336
6337 // window channel is invalid, so it should not receive any input event.
6338 window->assertNoEvents();
6339}
6340
6341TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006344 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006345 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006346 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6347
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006349 setFocusedWindow(window);
6350
6351 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006352 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006353
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006354 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006355 window->assertNoEvents();
6356}
6357
6358TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6360 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006361 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006362 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006363 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6365
6366 windowTop->setFocusable(true);
6367 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006368 mDispatcher->onWindowInfosChanged(
6369 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006370 setFocusedWindow(windowTop);
6371 windowTop->consumeFocusEvent(true);
6372
Chavi Weingarten847e8512023-03-29 00:26:09 +00006373 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006374 mDispatcher->onWindowInfosChanged(
6375 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006376 windowSecond->consumeFocusEvent(true);
6377 windowTop->consumeFocusEvent(false);
6378
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006380 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006381
6382 // Focused window should receive event.
6383 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6384}
6385
Chavi Weingarten847e8512023-03-29 00:26:09 +00006386TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6388 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006389 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006390 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006391 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006392 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6393
6394 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006395 windowSecond->setFocusable(false);
6396 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006397 mDispatcher->onWindowInfosChanged(
6398 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006399 setFocusedWindow(windowTop);
6400 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006401
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006403 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006404
6405 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006406 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006407 windowSecond->assertNoEvents();
6408}
6409
6410TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6412 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006413 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006414 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006415 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6416 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006417 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6418
6419 window->setFocusable(true);
6420 previousFocusedWindow->setFocusable(true);
6421 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006422 mDispatcher->onWindowInfosChanged(
6423 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006424 setFocusedWindow(previousFocusedWindow);
6425 previousFocusedWindow->consumeFocusEvent(true);
6426
6427 // Requesting focus on invisible window takes focus from currently focused window.
6428 setFocusedWindow(window);
6429 previousFocusedWindow->consumeFocusEvent(false);
6430
6431 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006433 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6434 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006435
6436 // Window does not get focus event or key down.
6437 window->assertNoEvents();
6438
6439 // Window becomes visible.
6440 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006441 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006442
6443 // Window receives focus event.
6444 window->consumeFocusEvent(true);
6445 // Focused window receives key down.
6446 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6447}
6448
Vishnu Nair599f1412021-06-21 10:39:58 -07006449TEST_F(InputDispatcherTest, DisplayRemoved) {
6450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6451 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006452 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006453 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6454
6455 // window is granted focus.
6456 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006457 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006458 setFocusedWindow(window);
6459 window->consumeFocusEvent(true);
6460
6461 // When a display is removed window loses focus.
6462 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6463 window->consumeFocusEvent(false);
6464}
6465
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006466/**
6467 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6468 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6469 * of the 'slipperyEnterWindow'.
6470 *
6471 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6472 * a way so that the touched location is no longer covered by the top window.
6473 *
6474 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6475 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6476 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6477 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6478 * with ACTION_DOWN).
6479 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6480 * window moved itself away from the touched location and had Flag::SLIPPERY.
6481 *
6482 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6483 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6484 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6485 *
6486 * In this test, we ensure that the event received by the bottom window has
6487 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6488 */
6489TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006490 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006491 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006492
6493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6495
6496 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006497 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006498 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006499 // Make sure this one overlaps the bottom window
6500 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6501 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6502 // one. Windows with the same owner are not considered to be occluding each other.
6503 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6504
6505 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006506 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006507 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6508
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006509 mDispatcher->onWindowInfosChanged(
6510 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006511
6512 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006513 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6514 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6515 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006516 slipperyExitWindow->consumeMotionDown();
6517 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006518 mDispatcher->onWindowInfosChanged(
6519 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006520
Prabir Pradhan678438e2023-04-13 19:32:51 +00006521 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6522 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6523 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006524
6525 slipperyExitWindow->consumeMotionCancel();
6526
6527 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6528 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6529}
6530
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006531/**
6532 * Two windows, one on the left and another on the right. The left window is slippery. The right
6533 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6534 * touch moves from the left window into the right window, the gesture should continue to go to the
6535 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6536 * reproduces a crash.
6537 */
6538TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6540
6541 sp<FakeWindowHandle> leftSlipperyWindow =
6542 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6543 leftSlipperyWindow->setSlippery(true);
6544 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6545
6546 sp<FakeWindowHandle> rightDropTouchesWindow =
6547 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6548 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6549 rightDropTouchesWindow->setDropInput(true);
6550
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006551 mDispatcher->onWindowInfosChanged(
6552 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006553
6554 // Start touch in the left window
6555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6556 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6557 .build());
6558 leftSlipperyWindow->consumeMotionDown();
6559
6560 // And move it into the right window
6561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6562 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6563 .build());
6564
6565 // Since the right window isn't eligible to receive input, touch does not slip.
6566 // The left window continues to receive the gesture.
6567 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6568 rightDropTouchesWindow->assertNoEvents();
6569}
6570
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006571/**
6572 * A single window is on screen first. Touch is injected into that window. Next, a second window
6573 * appears. Since the first window is slippery, touch will move from the first window to the second.
6574 */
6575TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6577 sp<FakeWindowHandle> originalWindow =
6578 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6579 originalWindow->setFrame(Rect(0, 0, 200, 200));
6580 originalWindow->setSlippery(true);
6581
6582 sp<FakeWindowHandle> appearingWindow =
6583 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6584 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6585
6586 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6587
6588 // Touch down on the original window
6589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6590 injectMotionEvent(*mDispatcher,
6591 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6592 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6593 .build()));
6594 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6595
6596 // Now, a new window appears. This could be, for example, a notification shade that appears
6597 // after user starts to drag down on the launcher window.
6598 mDispatcher->onWindowInfosChanged(
6599 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6601 injectMotionEvent(*mDispatcher,
6602 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6603 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6604 .build()));
6605 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6606 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6608 injectMotionEvent(*mDispatcher,
6609 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6610 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6611 .build()));
6612 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6613
6614 originalWindow->assertNoEvents();
6615 appearingWindow->assertNoEvents();
6616}
6617
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006618TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006619 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6621
6622 sp<FakeWindowHandle> leftWindow =
6623 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6624 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006625 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006626
6627 sp<FakeWindowHandle> rightSpy =
6628 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6629 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006630 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006631 rightSpy->setSpy(true);
6632 rightSpy->setTrustedOverlay(true);
6633
6634 sp<FakeWindowHandle> rightWindow =
6635 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6636 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006637 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006638
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006639 mDispatcher->onWindowInfosChanged(
6640 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006641
6642 // Touch in the left window
6643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6645 .build());
6646 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6647 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006648 ASSERT_NO_FATAL_FAILURE(
6649 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006650
6651 // Touch another finger over the right windows
6652 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6653 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6654 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6655 .build());
6656 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6657 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6658 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6659 mDispatcher->waitForIdle();
6660 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006661 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6662 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006663
6664 // Release finger over left window. The UP actions are not treated as device interaction.
6665 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6666 // is part of the UP action, we do not treat this as device interaction.
6667 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6668 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6669 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6670 .build());
6671 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6672 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6673 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6674 mDispatcher->waitForIdle();
6675 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6676
6677 // Move remaining finger
6678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6679 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6680 .build());
6681 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6682 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6683 mDispatcher->waitForIdle();
6684 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006685 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006686
6687 // Release all fingers
6688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6689 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6690 .build());
6691 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6692 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6693 mDispatcher->waitForIdle();
6694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6695}
6696
6697TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6699
6700 sp<FakeWindowHandle> window =
6701 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6702 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006703 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006706 setFocusedWindow(window);
6707 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6708
6709 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6710 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6711 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006712 ASSERT_NO_FATAL_FAILURE(
6713 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006714
6715 // The UP actions are not treated as device interaction.
6716 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6717 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6718 mDispatcher->waitForIdle();
6719 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6720}
6721
Prabir Pradhan5893d362023-11-17 04:30:40 +00006722TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6724
6725 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6726 ADISPLAY_ID_DEFAULT);
6727 left->setFrame(Rect(0, 0, 100, 100));
6728 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6729 "Right Window", ADISPLAY_ID_DEFAULT);
6730 right->setFrame(Rect(100, 0, 200, 100));
6731 sp<FakeWindowHandle> spy =
6732 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6733 spy->setFrame(Rect(0, 0, 200, 100));
6734 spy->setTrustedOverlay(true);
6735 spy->setSpy(true);
6736
6737 mDispatcher->onWindowInfosChanged(
6738 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6739
6740 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6741 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6742 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6743 mDispatcher->notifyMotion(notifyArgs);
6744
6745 const MotionEvent& leftEnter = left->consumeMotionEvent(
6746 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6747 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6748
6749 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6750 Not(WithEventId(notifyArgs.id)),
6751 Not(WithEventId(leftEnter.getId())),
6752 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6753
6754 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6755 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6756 {PointF{150, 50}});
6757 mDispatcher->notifyMotion(notifyArgs);
6758
6759 const MotionEvent& leftExit = left->consumeMotionEvent(
6760 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6761 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6762
6763 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6764 Not(WithEventId(notifyArgs.id)),
6765 Not(WithEventId(leftExit.getId())),
6766 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6767
6768 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6769}
6770
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006771class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6772protected:
6773 std::shared_ptr<FakeApplicationHandle> mApp;
6774 sp<FakeWindowHandle> mWindow;
6775
6776 virtual void SetUp() override {
6777 InputDispatcherTest::SetUp();
6778
6779 mApp = std::make_shared<FakeApplicationHandle>();
6780
6781 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6782 mWindow->setFrame(Rect(0, 0, 100, 100));
6783
6784 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6785 setFocusedWindow(mWindow);
6786 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6787 }
6788
6789 void setFallback(int32_t keycode) {
6790 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6791 return KeyEventBuilder(event).keyCode(keycode).build();
6792 });
6793 }
6794
6795 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006796 const KeyEvent& event = mWindow->consumeKey(handled);
6797 ASSERT_THAT(event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006798 }
6799};
6800
6801TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6802 mDispatcher->notifyKey(
6803 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6804 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6805 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6806}
6807
6808TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6809 mDispatcher->notifyKey(
6810 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6811 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6812 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6813}
6814
6815TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6816 mDispatcher->notifyKey(
6817 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6818
6819 // Do not handle this key event.
6820 consumeKey(/*handled=*/false,
6821 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6822 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6823
6824 // Since the policy did not request any fallback to be generated, ensure there are no events.
6825 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6826}
6827
6828TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6829 setFallback(AKEYCODE_B);
6830 mDispatcher->notifyKey(
6831 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6832
6833 // Do not handle this key event.
6834 consumeKey(/*handled=*/false,
6835 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6836
6837 // Since the key was not handled, ensure the fallback event was dispatched instead.
6838 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6839 consumeKey(/*handled=*/true,
6840 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6841 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6842
6843 // Release the original key, and ensure the fallback key is also released.
6844 mDispatcher->notifyKey(
6845 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6846 consumeKey(/*handled=*/false,
6847 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6848 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6849 consumeKey(/*handled=*/true,
6850 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6851 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6852
6853 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6854 mWindow->assertNoEvents();
6855}
6856
6857TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6858 setFallback(AKEYCODE_B);
6859 mDispatcher->notifyKey(
6860 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6861
6862 // Do not handle this key event, but handle the fallback.
6863 consumeKey(/*handled=*/false,
6864 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6865 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6866 consumeKey(/*handled=*/true,
6867 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6868 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6869
6870 // Release the original key, and ensure the fallback key is also released.
6871 mDispatcher->notifyKey(
6872 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6873 // But this time, the app handles the original key.
6874 consumeKey(/*handled=*/true,
6875 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6876 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6877 // Ensure the fallback key is canceled.
6878 consumeKey(/*handled=*/true,
6879 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6880 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6881
6882 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6883 mWindow->assertNoEvents();
6884}
6885
6886TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6887 setFallback(AKEYCODE_B);
6888 mDispatcher->notifyKey(
6889 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6890
6891 // Do not handle this key event.
6892 consumeKey(/*handled=*/false,
6893 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6894 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6895 // App does not handle the fallback either, so ensure another fallback is not generated.
6896 setFallback(AKEYCODE_C);
6897 consumeKey(/*handled=*/false,
6898 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6899 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6900
6901 // Release the original key, and ensure the fallback key is also released.
6902 setFallback(AKEYCODE_B);
6903 mDispatcher->notifyKey(
6904 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6905 consumeKey(/*handled=*/false,
6906 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6907 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6908 consumeKey(/*handled=*/false,
6909 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6910 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6911
6912 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6913 mWindow->assertNoEvents();
6914}
6915
6916TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6917 setFallback(AKEYCODE_B);
6918 mDispatcher->notifyKey(
6919 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6920
6921 // Do not handle this key event, so fallback is generated.
6922 consumeKey(/*handled=*/false,
6923 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6924 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6925 consumeKey(/*handled=*/true,
6926 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6927 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6928
6929 // Release the original key, but assume the policy is misbehaving and it
6930 // generates an inconsistent fallback to the one from the DOWN event.
6931 setFallback(AKEYCODE_C);
6932 mDispatcher->notifyKey(
6933 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6934 consumeKey(/*handled=*/false,
6935 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6936 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6937 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6938 consumeKey(/*handled=*/true,
6939 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6940 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6941
6942 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6943 mWindow->assertNoEvents();
6944}
6945
6946TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6947 setFallback(AKEYCODE_B);
6948 mDispatcher->notifyKey(
6949 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6950
6951 // Do not handle this key event, so fallback is generated.
6952 consumeKey(/*handled=*/false,
6953 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6954 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6955 consumeKey(/*handled=*/true,
6956 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6957 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6958
6959 // The original key is canceled.
6960 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6961 .keyCode(AKEYCODE_A)
6962 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6963 .build());
6964 consumeKey(/*handled=*/false,
6965 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6966 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6967 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6968 // Ensure the fallback key is also canceled due to the original key being canceled.
6969 consumeKey(/*handled=*/true,
6970 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6971 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6972
6973 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6974 mWindow->assertNoEvents();
6975}
6976
Garfield Tan1c7bc862020-01-28 13:24:04 -08006977class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6978protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006979 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6980 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006981
Chris Yea209fde2020-07-22 13:54:51 -07006982 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006983 sp<FakeWindowHandle> mWindow;
6984
6985 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006986 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006987 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006988 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006989 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006990 ASSERT_EQ(OK, mDispatcher->start());
6991
6992 setUpWindow();
6993 }
6994
6995 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006996 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006997 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006998
Vishnu Nair47074b82020-08-14 11:54:47 -07006999 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007000 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007001 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007002 mWindow->consumeFocusEvent(true);
7003 }
7004
Chris Ye2ad95392020-09-01 13:44:44 -07007005 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007006 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007007 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007008 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007009 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007010
7011 // Window should receive key down event.
7012 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7013 }
7014
7015 void expectKeyRepeatOnce(int32_t repeatCount) {
7016 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007017 mWindow->consumeKeyEvent(
7018 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007019 }
7020
Chris Ye2ad95392020-09-01 13:44:44 -07007021 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007022 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007023 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007024 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007025 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007026
7027 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007028 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007029 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007030 }
7031};
7032
7033TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007034 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007035 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7036 expectKeyRepeatOnce(repeatCount);
7037 }
7038}
7039
7040TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007041 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007042 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7043 expectKeyRepeatOnce(repeatCount);
7044 }
Harry Cutts33476232023-01-30 19:57:29 +00007045 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007046 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007047 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7048 expectKeyRepeatOnce(repeatCount);
7049 }
7050}
7051
7052TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007053 sendAndConsumeKeyDown(/*deviceId=*/1);
7054 expectKeyRepeatOnce(/*repeatCount=*/1);
7055 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007056 mWindow->assertNoEvents();
7057}
7058
7059TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007060 sendAndConsumeKeyDown(/*deviceId=*/1);
7061 expectKeyRepeatOnce(/*repeatCount=*/1);
7062 sendAndConsumeKeyDown(/*deviceId=*/2);
7063 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007064 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007065 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007066 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007067 expectKeyRepeatOnce(/*repeatCount=*/2);
7068 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007069 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007070 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007071 mWindow->assertNoEvents();
7072}
7073
7074TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007075 sendAndConsumeKeyDown(/*deviceId=*/1);
7076 expectKeyRepeatOnce(/*repeatCount=*/1);
7077 sendAndConsumeKeyDown(/*deviceId=*/2);
7078 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007079 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007080 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007081 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007082 mWindow->assertNoEvents();
7083}
7084
liushenxiang42232912021-05-21 20:24:09 +08007085TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7086 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007087 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007088 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007089 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7090 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7091 mWindow->assertNoEvents();
7092}
7093
Garfield Tan1c7bc862020-01-28 13:24:04 -08007094TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007095 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007096 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007097 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007098 const KeyEvent& repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007099 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007100 IdGenerator::getSource(repeatEvent.getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007101 }
7102}
7103
7104TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007105 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007106 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007107
7108 std::unordered_set<int32_t> idSet;
7109 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007110 const KeyEvent& repeatEvent = mWindow->consumeKey();
7111 int32_t id = repeatEvent.getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007112 EXPECT_EQ(idSet.end(), idSet.find(id));
7113 idSet.insert(id);
7114 }
7115}
7116
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007117/* Test InputDispatcher for MultiDisplay */
7118class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7119public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007120 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007121 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007122
Chris Yea209fde2020-07-22 13:54:51 -07007123 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007124 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007125 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007126
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007127 // Set focus window for primary display, but focused display would be second one.
7128 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007129 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007130 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7131
Vishnu Nair958da932020-08-21 17:12:37 -07007132 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007133 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007134
Chris Yea209fde2020-07-22 13:54:51 -07007135 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007136 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007137 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007138 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007139 // Set focus display to second one.
7140 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7141 // Set focus window for second display.
7142 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007143 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007144 mDispatcher->onWindowInfosChanged(
7145 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007146 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007147 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007148 }
7149
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007150 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007151 InputDispatcherTest::TearDown();
7152
Chris Yea209fde2020-07-22 13:54:51 -07007153 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007154 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007155 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007156 windowInSecondary.clear();
7157 }
7158
7159protected:
Chris Yea209fde2020-07-22 13:54:51 -07007160 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007161 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007162 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007163 sp<FakeWindowHandle> windowInSecondary;
7164};
7165
7166TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7167 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007169 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007171 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007172 windowInSecondary->assertNoEvents();
7173
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007174 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007176 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007178 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007179 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007180}
7181
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007182TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007183 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007185 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007186 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007187 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007188 windowInSecondary->assertNoEvents();
7189
7190 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007192 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007193 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007194 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007195
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007196 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007197 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007198
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007199 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007200 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007201
7202 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007203 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007204 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007205 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007206 windowInSecondary->assertNoEvents();
7207}
7208
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007209// Test per-display input monitors for motion event.
7210TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007211 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007212 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007213 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007214 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007215
7216 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007218 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007220 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007221 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007222 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007223 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007224
7225 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007227 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007229 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007230 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007231 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007232 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007233
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007234 // Lift up the touch from the second display
7235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7238 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7239 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7240
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007241 // Test inject a non-pointer motion event.
7242 // If specific a display, it will dispatch to the focused window of particular display,
7243 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007245 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007247 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007248 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007249 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007250 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007251}
7252
7253// Test per-display input monitors for key event.
7254TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007255 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007256 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007257 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007258 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007259 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007260
7261 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007263 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007264 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007265 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007266 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007267 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007268}
7269
Vishnu Nair958da932020-08-21 17:12:37 -07007270TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7271 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007272 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007273 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007274 mDispatcher->onWindowInfosChanged(
7275 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7276 *windowInSecondary->getInfo()},
7277 {},
7278 0,
7279 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007280 setFocusedWindow(secondWindowInPrimary);
7281 windowInPrimary->consumeFocusEvent(false);
7282 secondWindowInPrimary->consumeFocusEvent(true);
7283
7284 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7286 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007287 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007288 windowInPrimary->assertNoEvents();
7289 windowInSecondary->assertNoEvents();
7290 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7291}
7292
Arthur Hungdfd528e2021-12-08 13:23:04 +00007293TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7294 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007295 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007296 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007297 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007298
7299 // Test touch down on primary display.
7300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007301 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7303 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7304 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7305
7306 // Test touch down on second display.
7307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007308 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007309 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7310 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7311 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7312
7313 // Trigger cancel touch.
7314 mDispatcher->cancelCurrentTouch();
7315 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7316 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7317 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7318 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7319
7320 // Test inject a move motion event, no window/monitor should receive the event.
7321 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007322 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007323 ADISPLAY_ID_DEFAULT, {110, 200}))
7324 << "Inject motion event should return InputEventInjectionResult::FAILED";
7325 windowInPrimary->assertNoEvents();
7326 monitorInPrimary.assertNoEvents();
7327
7328 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007329 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007330 SECOND_DISPLAY_ID, {110, 200}))
7331 << "Inject motion event should return InputEventInjectionResult::FAILED";
7332 windowInSecondary->assertNoEvents();
7333 monitorInSecondary.assertNoEvents();
7334}
7335
Hu Guocb134f12023-12-23 13:42:44 +00007336/**
7337 * Send a key to the primary display and to the secondary display.
7338 * Then cause the key on the primary display to be canceled by sending in a stale key.
7339 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7340 * does not get canceled.
7341 */
7342TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7343 // Send a key down on primary display
7344 mDispatcher->notifyKey(
7345 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7346 .displayId(ADISPLAY_ID_DEFAULT)
7347 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7348 .build());
7349 windowInPrimary->consumeKeyEvent(
7350 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7351 windowInSecondary->assertNoEvents();
7352
7353 // Send a key down on second display
7354 mDispatcher->notifyKey(
7355 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7356 .displayId(SECOND_DISPLAY_ID)
7357 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7358 .build());
7359 windowInSecondary->consumeKeyEvent(
7360 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7361 windowInPrimary->assertNoEvents();
7362
7363 // Send a valid key up event on primary display that will be dropped because it is stale
7364 NotifyKeyArgs staleKeyUp =
7365 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7366 .displayId(ADISPLAY_ID_DEFAULT)
7367 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7368 .build();
7369 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7370 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7371 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7372 mDispatcher->notifyKey(staleKeyUp);
7373
7374 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7375 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7376 // receive any events.
7377 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7378 WithDisplayId(ADISPLAY_ID_DEFAULT),
7379 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7380 windowInSecondary->assertNoEvents();
7381}
7382
7383/**
7384 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7385 */
7386TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7387 // Send touch down on primary display.
7388 mDispatcher->notifyMotion(
7389 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7390 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7391 .displayId(ADISPLAY_ID_DEFAULT)
7392 .build());
7393 windowInPrimary->consumeMotionEvent(
7394 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7395 windowInSecondary->assertNoEvents();
7396
7397 // Send touch down on second display.
7398 mDispatcher->notifyMotion(
7399 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7400 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7401 .displayId(SECOND_DISPLAY_ID)
7402 .build());
7403 windowInPrimary->assertNoEvents();
7404 windowInSecondary->consumeMotionEvent(
7405 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7406
7407 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7408 NotifyMotionArgs staleMotionUp =
7409 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7410 .displayId(ADISPLAY_ID_DEFAULT)
7411 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7412 .build();
7413 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7414 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7415 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7416 mDispatcher->notifyMotion(staleMotionUp);
7417
7418 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7419 // events, where we would cancel the current keys instead.
7420 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7421 windowInSecondary->assertNoEvents();
7422}
7423
Jackal Guof9696682018-10-05 12:23:23 +08007424class InputFilterTest : public InputDispatcherTest {
7425protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007426 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7427 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007428 NotifyMotionArgs motionArgs;
7429
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007430 motionArgs =
7431 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007432 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007433 motionArgs =
7434 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007435 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007436 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007437 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007438 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007439 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007440 } else {
7441 mFakePolicy->assertFilterInputEventWasNotCalled();
7442 }
7443 }
7444
7445 void testNotifyKey(bool expectToBeFiltered) {
7446 NotifyKeyArgs keyArgs;
7447
7448 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007449 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007450 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007451 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007452 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007453
7454 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007455 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007456 } else {
7457 mFakePolicy->assertFilterInputEventWasNotCalled();
7458 }
7459 }
7460};
7461
7462// Test InputFilter for MotionEvent
7463TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7464 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007465 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7466 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007467
7468 // Enable InputFilter
7469 mDispatcher->setInputFilterEnabled(true);
7470 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007471 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7472 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007473
7474 // Disable InputFilter
7475 mDispatcher->setInputFilterEnabled(false);
7476 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007477 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7478 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007479}
7480
7481// Test InputFilter for KeyEvent
7482TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7483 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007484 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007485
7486 // Enable InputFilter
7487 mDispatcher->setInputFilterEnabled(true);
7488 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007489 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007490
7491 // Disable InputFilter
7492 mDispatcher->setInputFilterEnabled(false);
7493 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007494 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007495}
7496
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007497// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7498// logical display coordinate space.
7499TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7500 ui::Transform firstDisplayTransform;
7501 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7502 ui::Transform secondDisplayTransform;
7503 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7504
7505 std::vector<gui::DisplayInfo> displayInfos(2);
7506 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7507 displayInfos[0].transform = firstDisplayTransform;
7508 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7509 displayInfos[1].transform = secondDisplayTransform;
7510
Patrick Williamsd828f302023-04-28 17:52:08 -05007511 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007512
7513 // Enable InputFilter
7514 mDispatcher->setInputFilterEnabled(true);
7515
7516 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007517 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7518 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007519}
7520
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007521class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7522protected:
7523 virtual void SetUp() override {
7524 InputDispatcherTest::SetUp();
7525
7526 /**
7527 * We don't need to enable input filter to test the injected event policy, but we enabled it
7528 * here to make the tests more realistic, since this policy only matters when inputfilter is
7529 * on.
7530 */
7531 mDispatcher->setInputFilterEnabled(true);
7532
7533 std::shared_ptr<InputApplicationHandle> application =
7534 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007535 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7536 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007537
7538 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7539 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007540 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007541 setFocusedWindow(mWindow);
7542 mWindow->consumeFocusEvent(true);
7543 }
7544
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007545 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7546 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007547 KeyEvent event;
7548
7549 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7550 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7551 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007552 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007553 const int32_t additionalPolicyFlags =
7554 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007556 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007557 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007558 policyFlags | additionalPolicyFlags));
7559
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007560 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007561 }
7562
7563 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7564 int32_t flags) {
7565 MotionEvent event;
7566 PointerProperties pointerProperties[1];
7567 PointerCoords pointerCoords[1];
7568 pointerProperties[0].clear();
7569 pointerProperties[0].id = 0;
7570 pointerCoords[0].clear();
7571 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7572 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7573
7574 ui::Transform identityTransform;
7575 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7576 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7577 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7578 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7579 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007580 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007581 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007582 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007583
7584 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007586 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007587 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007588 policyFlags | additionalPolicyFlags));
7589
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007590 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007591 }
7592
7593private:
7594 sp<FakeWindowHandle> mWindow;
7595};
7596
7597TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007598 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7599 // filter. Without it, the event will no different from a regularly injected event, and the
7600 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007601 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7602 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007603}
7604
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007605TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007606 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007607 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007608 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7609}
7610
7611TEST_F(InputFilterInjectionPolicyTest,
7612 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7613 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007614 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007615 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007616}
7617
7618TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007619 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7620 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007621}
7622
chaviwfd6d3512019-03-25 13:23:49 -07007623class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007624 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007625 InputDispatcherTest::SetUp();
7626
Chris Yea209fde2020-07-22 13:54:51 -07007627 std::shared_ptr<FakeApplicationHandle> application =
7628 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007629 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007630 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007631 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007632
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007633 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007634 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007635 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007636
7637 // Set focused application.
7638 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007639 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007640
7641 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007642 mDispatcher->onWindowInfosChanged(
7643 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007644 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007645 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007646 }
7647
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007648 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007649 InputDispatcherTest::TearDown();
7650
7651 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007652 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007653 }
7654
7655protected:
7656 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007657 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007658 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007659};
7660
7661// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7662// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7663// the onPointerDownOutsideFocus callback.
7664TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007666 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007667 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007669 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007670
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007671 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007672 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7673}
7674
7675// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7676// DOWN on the window that doesn't have focus. Ensure no window received the
7677// onPointerDownOutsideFocus callback.
7678TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007680 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7681 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007683 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007684
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007685 ASSERT_TRUE(mDispatcher->waitForIdle());
7686 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007687}
7688
7689// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7690// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7691TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007693 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007695 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007696
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007697 ASSERT_TRUE(mDispatcher->waitForIdle());
7698 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007699}
7700
7701// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7702// DOWN on the window that already has focus. Ensure no window received the
7703// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007704TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007706 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007707 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007709 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007710
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007711 ASSERT_TRUE(mDispatcher->waitForIdle());
7712 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007713}
7714
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007715// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7716// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7717TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7718 const MotionEvent event =
7719 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7720 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007721 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007722 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7723 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7726 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7727
7728 ASSERT_TRUE(mDispatcher->waitForIdle());
7729 mFakePolicy->assertOnPointerDownWasNotCalled();
7730 // Ensure that the unfocused window did not receive any FOCUS events.
7731 mUnfocusedWindow->assertNoEvents();
7732}
7733
chaviwaf87b3e2019-10-01 16:59:28 -07007734// These tests ensures we can send touch events to a single client when there are multiple input
7735// windows that point to the same client token.
7736class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7737 virtual void SetUp() override {
7738 InputDispatcherTest::SetUp();
7739
Chris Yea209fde2020-07-22 13:54:51 -07007740 std::shared_ptr<FakeApplicationHandle> application =
7741 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007742 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7743 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007744 mWindow1->setFrame(Rect(0, 0, 100, 100));
7745
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00007746 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007747 mWindow2->setFrame(Rect(100, 100, 200, 200));
7748
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007749 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007750 }
7751
7752protected:
7753 sp<FakeWindowHandle> mWindow1;
7754 sp<FakeWindowHandle> mWindow2;
7755
7756 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007757 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007758 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7759 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007760 }
7761
7762 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7763 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007764 const std::string name = window->getName();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007765 const MotionEvent& motionEvent =
7766 window->consumeMotionEvent(WithMotionAction(expectedAction));
chaviwaf87b3e2019-10-01 16:59:28 -07007767
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007768 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007769
7770 for (size_t i = 0; i < points.size(); i++) {
7771 float expectedX = points[i].x;
7772 float expectedY = points[i].y;
7773
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007774 EXPECT_EQ(expectedX, motionEvent.getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007775 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007776 << ", got " << motionEvent.getX(i);
7777 EXPECT_EQ(expectedY, motionEvent.getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007778 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007779 << ", got " << motionEvent.getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007780 }
7781 }
chaviw9eaa22c2020-07-01 16:21:27 -07007782
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007783 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007784 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007785 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7786 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007787
7788 // Always consume from window1 since it's the window that has the InputReceiver
7789 consumeMotionEvent(mWindow1, action, expectedPoints);
7790 }
chaviwaf87b3e2019-10-01 16:59:28 -07007791};
7792
7793TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7794 // Touch Window 1
7795 PointF touchedPoint = {10, 10};
7796 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007797 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007798
7799 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007800 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007801
7802 // Touch Window 2
7803 touchedPoint = {150, 150};
7804 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007805 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007806}
7807
chaviw9eaa22c2020-07-01 16:21:27 -07007808TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7809 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007810 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007811 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007812
7813 // Touch Window 1
7814 PointF touchedPoint = {10, 10};
7815 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007816 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007817 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007818 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007819
7820 // Touch Window 2
7821 touchedPoint = {150, 150};
7822 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007823 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7824 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007825
chaviw9eaa22c2020-07-01 16:21:27 -07007826 // Update the transform so rotation is set
7827 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007828 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007829 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7830 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007831}
7832
chaviw9eaa22c2020-07-01 16:21:27 -07007833TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007834 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007835 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007836
7837 // Touch Window 1
7838 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7839 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007840 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007841
7842 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007843 touchedPoints.push_back(PointF{150, 150});
7844 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007845 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007846
chaviw9eaa22c2020-07-01 16:21:27 -07007847 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007848 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007849 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007850
chaviw9eaa22c2020-07-01 16:21:27 -07007851 // Update the transform so rotation is set for Window 2
7852 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007853 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007854 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007855 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007856}
7857
chaviw9eaa22c2020-07-01 16:21:27 -07007858TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007859 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007860 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007861
7862 // Touch Window 1
7863 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7864 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007865 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007866
7867 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007868 touchedPoints.push_back(PointF{150, 150});
7869 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007870
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007871 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007872
7873 // Move both windows
7874 touchedPoints = {{20, 20}, {175, 175}};
7875 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7876 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7877
chaviw9eaa22c2020-07-01 16:21:27 -07007878 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007879
chaviw9eaa22c2020-07-01 16:21:27 -07007880 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007881 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007882 expectedPoints.pop_back();
7883
7884 // Touch Window 2
7885 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007886 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007887 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007888 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007889
7890 // Move both windows
7891 touchedPoints = {{20, 20}, {175, 175}};
7892 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7893 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7894
7895 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007896}
7897
7898TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7899 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007900 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007901
7902 // Touch Window 1
7903 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7904 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007905 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007906
7907 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007908 touchedPoints.push_back(PointF{150, 150});
7909 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007910
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007911 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007912
7913 // Move both windows
7914 touchedPoints = {{20, 20}, {175, 175}};
7915 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7916 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7917
chaviw9eaa22c2020-07-01 16:21:27 -07007918 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007919}
7920
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007921/**
7922 * When one of the windows is slippery, the touch should not slip into the other window with the
7923 * same input channel.
7924 */
7925TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7926 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007927 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007928
7929 // Touch down in window 1
7930 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7931 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7932 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7933
7934 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7935 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7936 // getting generated.
7937 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7938 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7939
7940 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7941}
7942
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007943/**
7944 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7945 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7946 * that the pointer is hovering over may have a different transform.
7947 */
7948TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007949 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007950
7951 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7953 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7954 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007955 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7956 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007957 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7959 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7960 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007961 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7962 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7963 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7964}
7965
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007966class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7967 virtual void SetUp() override {
7968 InputDispatcherTest::SetUp();
7969
Chris Yea209fde2020-07-22 13:54:51 -07007970 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007971 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007972 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7973 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007974 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007975 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007976 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007977
7978 // Set focused application.
7979 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7980
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007981 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007982 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007983 mWindow->consumeFocusEvent(true);
7984 }
7985
7986 virtual void TearDown() override {
7987 InputDispatcherTest::TearDown();
7988 mWindow.clear();
7989 }
7990
7991protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007992 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007993 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007994 sp<FakeWindowHandle> mWindow;
7995 static constexpr PointF WINDOW_LOCATION = {20, 20};
7996
7997 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007998 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7999 .x(WINDOW_LOCATION.x)
8000 .y(WINDOW_LOCATION.y);
8001 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8002 .pointer(touchingPointer)
8003 .build());
8004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8005 .pointer(touchingPointer)
8006 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008007 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008008
8009 sp<FakeWindowHandle> addSpyWindow() {
8010 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008011 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008012 spy->setTrustedOverlay(true);
8013 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008014 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008015 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008016 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008017 return spy;
8018 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008019};
8020
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021// Send a tap and respond, which should not cause an ANR.
8022TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8023 tapOnWindow();
8024 mWindow->consumeMotionDown();
8025 mWindow->consumeMotionUp();
8026 ASSERT_TRUE(mDispatcher->waitForIdle());
8027 mFakePolicy->assertNotifyAnrWasNotCalled();
8028}
8029
8030// Send a regular key and respond, which should not cause an ANR.
8031TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008033 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8034 ASSERT_TRUE(mDispatcher->waitForIdle());
8035 mFakePolicy->assertNotifyAnrWasNotCalled();
8036}
8037
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008038TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8039 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008040 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008041 mWindow->consumeFocusEvent(false);
8042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008043 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008044 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8045 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008046 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008048 // Key will not go to window because we have no focused window.
8049 // The 'no focused window' ANR timer should start instead.
8050
8051 // Now, the focused application goes away.
8052 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8053 // The key should get dropped and there should be no ANR.
8054
8055 ASSERT_TRUE(mDispatcher->waitForIdle());
8056 mFakePolicy->assertNotifyAnrWasNotCalled();
8057}
8058
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008059// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008060// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8061// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008062TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008064 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008065 WINDOW_LOCATION));
8066
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008067 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8068 ASSERT_TRUE(sequenceNum);
8069 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008070 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008071
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008072 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008073 mWindow->consumeMotionEvent(
8074 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008075 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008076 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008077}
8078
8079// Send a key to the app and have the app not respond right away.
8080TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8081 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008083 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
8084 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008085 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008086 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008087 ASSERT_TRUE(mDispatcher->waitForIdle());
8088}
8089
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008090// We have a focused application, but no focused window
8091TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008092 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008093 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008094 mWindow->consumeFocusEvent(false);
8095
8096 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008098 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008099 WINDOW_LOCATION));
8100 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8101 mDispatcher->waitForIdle();
8102 mFakePolicy->assertNotifyAnrWasNotCalled();
8103
8104 // Once a focused event arrives, we get an ANR for this application
8105 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8106 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008107 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008108 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008109 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008110 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008111 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008112 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008113 ASSERT_TRUE(mDispatcher->waitForIdle());
8114}
8115
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008116/**
8117 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8118 * there will not be an ANR.
8119 */
8120TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8121 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008122 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008123 mWindow->consumeFocusEvent(false);
8124
8125 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008126 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8127 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008128 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8129 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8130
8131 // Define a valid key down event that is stale (too old).
8132 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008133 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008134 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008135
8136 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8137
8138 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008139 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008140 InputEventInjectionSync::WAIT_FOR_RESULT,
8141 INJECT_EVENT_TIMEOUT, policyFlags);
8142 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8143 << "Injection should fail because the event is stale";
8144
8145 ASSERT_TRUE(mDispatcher->waitForIdle());
8146 mFakePolicy->assertNotifyAnrWasNotCalled();
8147 mWindow->assertNoEvents();
8148}
8149
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008150// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008151// Make sure that we don't notify policy twice about the same ANR.
8152TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008153 const std::chrono::duration appTimeout = 400ms;
8154 mApplication->setDispatchingTimeout(appTimeout);
8155 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8156
Vishnu Nair47074b82020-08-14 11:54:47 -07008157 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008158 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008159 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008160
8161 // Once a focused event arrives, we get an ANR for this application
8162 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8163 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008164 const std::chrono::duration eventInjectionTimeout = 100ms;
8165 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008166 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008167 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008168 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8169 /*allowKeyRepeat=*/false);
8170 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8171 << "result=" << ftl::enum_string(result);
8172 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8173 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8174 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8175 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008176
Vishnu Naire4df8752022-09-08 09:17:55 -07008177 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008178 // ANR should not be raised again. It is up to policy to do that if it desires.
8179 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008180
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008181 // If we now get a focused window, the ANR should stop, but the policy handles that via
8182 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008183 ASSERT_TRUE(mDispatcher->waitForIdle());
8184}
8185
8186// We have a focused application, but no focused window
8187TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008188 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008189 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008190 mWindow->consumeFocusEvent(false);
8191
8192 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008193 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008194
Vishnu Naire4df8752022-09-08 09:17:55 -07008195 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8196 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008197
8198 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008199 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008200 ASSERT_TRUE(mDispatcher->waitForIdle());
8201 mWindow->assertNoEvents();
8202}
8203
8204/**
8205 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8206 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8207 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8208 * the ANR mechanism should still work.
8209 *
8210 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8211 * DOWN event, while not responding on the second one.
8212 */
8213TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8214 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008215 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008216 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8217 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8218 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008219 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008220
8221 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008222 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008223 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8224 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8225 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008226 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008227
8228 // We have now sent down and up. Let's consume first event and then ANR on the second.
8229 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8230 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008231 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008232}
8233
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008234// A spy window can receive an ANR
8235TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8236 sp<FakeWindowHandle> spy = addSpyWindow();
8237
8238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008239 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008240 WINDOW_LOCATION));
8241 mWindow->consumeMotionDown();
8242
8243 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8244 ASSERT_TRUE(sequenceNum);
8245 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008246 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008247
8248 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008249 spy->consumeMotionEvent(
8250 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008251 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008252 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008253}
8254
8255// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008256// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008257TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8258 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008259
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008261 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008262 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008264
8265 // Stuck on the ACTION_UP
8266 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008267 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008268
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008269 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008270 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008271 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8272 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008273
8274 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8275 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008276 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008277 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008278 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008279}
8280
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008281// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008282// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008283TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8284 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008285
8286 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008287 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8288 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008289
8290 mWindow->consumeMotionDown();
8291 // Stuck on the ACTION_UP
8292 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008293 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008294
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008295 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008296 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008297 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8298 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008299
8300 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8301 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008302 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008303 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008304 spy->assertNoEvents();
8305}
8306
8307TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008308 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008309
Prabir Pradhanfb549072023-10-05 19:17:36 +00008310 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008311
8312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008313 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008314 WINDOW_LOCATION));
8315
8316 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8317 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8318 ASSERT_TRUE(consumeSeq);
8319
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008320 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8321 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008322
8323 monitor.finishEvent(*consumeSeq);
8324 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8325
8326 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008327 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008328}
8329
8330// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8331// process events, you don't get an anr. When the window later becomes unresponsive again, you
8332// get an ANR again.
8333// 1. tap -> block on ACTION_UP -> receive ANR
8334// 2. consume all pending events (= queue becomes healthy again)
8335// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8336TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8337 tapOnWindow();
8338
8339 mWindow->consumeMotionDown();
8340 // Block on ACTION_UP
8341 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008342 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008343 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8344 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008345 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008346 mWindow->assertNoEvents();
8347
8348 tapOnWindow();
8349 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008350 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008351 mWindow->consumeMotionUp();
8352
8353 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008354 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008355 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008356 mWindow->assertNoEvents();
8357}
8358
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008359// If a connection remains unresponsive for a while, make sure policy is only notified once about
8360// it.
8361TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008363 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008364 WINDOW_LOCATION));
8365
8366 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008367 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008368 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008369 // 'notifyConnectionUnresponsive' should only be called once per connection
8370 mFakePolicy->assertNotifyAnrWasNotCalled();
8371 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008372 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008373 mWindow->consumeMotionEvent(
8374 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008375 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008376 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008377 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008378 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008379}
8380
8381/**
8382 * 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 -07008383 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008384 *
8385 * Warning!!!
8386 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8387 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008388 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008389 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8390 *
8391 * If that value changes, this test should also change.
8392 */
8393TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8394 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008395 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008396
8397 tapOnWindow();
8398 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8399 ASSERT_TRUE(downSequenceNum);
8400 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8401 ASSERT_TRUE(upSequenceNum);
8402 // Don't finish the events yet, and send a key
8403 // Injection will "succeed" because we will eventually give up and send the key to the focused
8404 // window even if motions are still being processed. But because the injection timeout is short,
8405 // we will receive INJECTION_TIMED_OUT as the result.
8406
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008407 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008408 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8409 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008410 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008411 // Key will not be sent to the window, yet, because the window is still processing events
8412 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008413 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8414 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8415 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8416 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008417
8418 std::this_thread::sleep_for(500ms);
8419 // if we wait long enough though, dispatcher will give up, and still send the key
8420 // to the focused window, even though we have not yet finished the motion event
8421 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8422 mWindow->finishEvent(*downSequenceNum);
8423 mWindow->finishEvent(*upSequenceNum);
8424}
8425
8426/**
8427 * If a window is processing a motion event, and then a key event comes in, the key event should
8428 * not go to the focused window until the motion is processed.
8429 * If then a new motion comes in, then the pending key event should be going to the currently
8430 * focused window right away.
8431 */
8432TEST_F(InputDispatcherSingleWindowAnr,
8433 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8434 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008435 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008436
8437 tapOnWindow();
8438 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8439 ASSERT_TRUE(downSequenceNum);
8440 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8441 ASSERT_TRUE(upSequenceNum);
8442 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008443 mDispatcher->notifyKey(
8444 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8445 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8446 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008447 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008448 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8449 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8450 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8451 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008452
8453 // Now tap down again. It should cause the pending key to go to the focused window right away.
8454 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008455 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8456 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008457 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8458 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008459 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8460 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008461 mWindow->assertNoEvents();
8462}
8463
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008464/**
8465 * Send an event to the app and have the app not respond right away.
8466 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8467 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8468 * At some point, the window becomes responsive again.
8469 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8470 */
8471TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8473 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8474 .build());
8475
8476 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8477 ASSERT_TRUE(sequenceNum);
8478 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8479 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8480
8481 mWindow->finishEvent(*sequenceNum);
8482 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8483 ASSERT_TRUE(mDispatcher->waitForIdle());
8484 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8485
8486 // Now that the window is responsive, let's continue the gesture.
8487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8488 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8489 .build());
8490
8491 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8492 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8493 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8494 .build());
8495
8496 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8497 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8498 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8499 .build());
8500 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8501 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8502 .build());
8503 // We already canceled this pointer, so the window shouldn't get any new events.
8504 mWindow->assertNoEvents();
8505
8506 // Start another one.
8507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8508 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8509 .build());
8510 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8511}
8512
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008513class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8514 virtual void SetUp() override {
8515 InputDispatcherTest::SetUp();
8516
Chris Yea209fde2020-07-22 13:54:51 -07008517 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008518 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008519 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8520 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008521 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008522 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008523 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008524
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008525 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8526 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008527 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008528 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008529
8530 // Set focused application.
8531 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008532 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008533
8534 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008535 mDispatcher->onWindowInfosChanged(
8536 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008537 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008538 mFocusedWindow->consumeFocusEvent(true);
8539 }
8540
8541 virtual void TearDown() override {
8542 InputDispatcherTest::TearDown();
8543
8544 mUnfocusedWindow.clear();
8545 mFocusedWindow.clear();
8546 }
8547
8548protected:
Chris Yea209fde2020-07-22 13:54:51 -07008549 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008550 sp<FakeWindowHandle> mUnfocusedWindow;
8551 sp<FakeWindowHandle> mFocusedWindow;
8552 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8553 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8554 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8555
8556 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8557
8558 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8559
8560private:
8561 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008563 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008564 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008566 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008567 location));
8568 }
8569};
8570
8571// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8572// should be ANR'd first.
8573TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008575 injectMotionEvent(*mDispatcher,
8576 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8577 AINPUT_SOURCE_TOUCHSCREEN)
8578 .pointer(PointerBuilder(0, ToolType::FINGER)
8579 .x(FOCUSED_WINDOW_LOCATION.x)
8580 .y(FOCUSED_WINDOW_LOCATION.y))
8581 .build()));
8582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8583 injectMotionEvent(*mDispatcher,
8584 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8585 AINPUT_SOURCE_TOUCHSCREEN)
8586 .pointer(PointerBuilder(0, ToolType::FINGER)
8587 .x(FOCUSED_WINDOW_LOCATION.x)
8588 .y(FOCUSED_WINDOW_LOCATION.y))
8589 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008590 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008591 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008592 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008593 // We consumed all events, so no ANR
8594 ASSERT_TRUE(mDispatcher->waitForIdle());
8595 mFakePolicy->assertNotifyAnrWasNotCalled();
8596
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008598 injectMotionEvent(*mDispatcher,
8599 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8600 AINPUT_SOURCE_TOUCHSCREEN)
8601 .pointer(PointerBuilder(0, ToolType::FINGER)
8602 .x(FOCUSED_WINDOW_LOCATION.x)
8603 .y(FOCUSED_WINDOW_LOCATION.y))
8604 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008605 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8606 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008607
8608 const std::chrono::duration timeout =
8609 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008610 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008611
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008612 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008613 mFocusedWindow->consumeMotionDown();
8614 // This cancel is generated because the connection was unresponsive
8615 mFocusedWindow->consumeMotionCancel();
8616 mFocusedWindow->assertNoEvents();
8617 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008618 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008619 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8620 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008621 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008622}
8623
8624// If we have 2 windows with identical timeouts that are both unresponsive,
8625// it doesn't matter which order they should have ANR.
8626// But we should receive ANR for both.
8627TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8628 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008629 mUnfocusedWindow->setDispatchingTimeout(
8630 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008631 mDispatcher->onWindowInfosChanged(
8632 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008633
8634 tapOnFocusedWindow();
8635 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008636 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008637 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8638 mFocusedWindow->getDispatchingTimeout(
8639 DISPATCHING_TIMEOUT)),
8640 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8641
8642 ASSERT_THAT(anrConnectionTokens,
8643 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8644 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008645
8646 ASSERT_TRUE(mDispatcher->waitForIdle());
8647 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008648
8649 mFocusedWindow->consumeMotionDown();
8650 mFocusedWindow->consumeMotionUp();
8651 mUnfocusedWindow->consumeMotionOutside();
8652
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008653 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8654 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008655
8656 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008657 ASSERT_THAT(responsiveTokens,
8658 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8659 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008660 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008661}
8662
8663// If a window is already not responding, the second tap on the same window should be ignored.
8664// We should also log an error to account for the dropped event (not tested here).
8665// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8666TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8667 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008668 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008669 // Receive the events, but don't respond
8670 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8671 ASSERT_TRUE(downEventSequenceNum);
8672 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8673 ASSERT_TRUE(upEventSequenceNum);
8674 const std::chrono::duration timeout =
8675 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008676 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008677
8678 // Tap once again
8679 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008680 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008681 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008682 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008684 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008685 FOCUSED_WINDOW_LOCATION));
8686 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8687 // valid touch target
8688 mUnfocusedWindow->assertNoEvents();
8689
8690 // Consume the first tap
8691 mFocusedWindow->finishEvent(*downEventSequenceNum);
8692 mFocusedWindow->finishEvent(*upEventSequenceNum);
8693 ASSERT_TRUE(mDispatcher->waitForIdle());
8694 // The second tap did not go to the focused window
8695 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008696 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008697 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8698 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008699 mFakePolicy->assertNotifyAnrWasNotCalled();
8700}
8701
8702// If you tap outside of all windows, there will not be ANR
8703TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008704 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008705 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008706 LOCATION_OUTSIDE_ALL_WINDOWS));
8707 ASSERT_TRUE(mDispatcher->waitForIdle());
8708 mFakePolicy->assertNotifyAnrWasNotCalled();
8709}
8710
8711// Since the focused window is paused, tapping on it should not produce any events
8712TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8713 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008714 mDispatcher->onWindowInfosChanged(
8715 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008716
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008717 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008718 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008719 FOCUSED_WINDOW_LOCATION));
8720
8721 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8722 ASSERT_TRUE(mDispatcher->waitForIdle());
8723 // Should not ANR because the window is paused, and touches shouldn't go to it
8724 mFakePolicy->assertNotifyAnrWasNotCalled();
8725
8726 mFocusedWindow->assertNoEvents();
8727 mUnfocusedWindow->assertNoEvents();
8728}
8729
8730/**
8731 * 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 -07008732 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008733 * If a different window becomes focused at this time, the key should go to that window instead.
8734 *
8735 * Warning!!!
8736 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8737 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008738 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008739 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8740 *
8741 * If that value changes, this test should also change.
8742 */
8743TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8744 // Set a long ANR timeout to prevent it from triggering
8745 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008746 mDispatcher->onWindowInfosChanged(
8747 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008748
8749 tapOnUnfocusedWindow();
8750 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8751 ASSERT_TRUE(downSequenceNum);
8752 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8753 ASSERT_TRUE(upSequenceNum);
8754 // Don't finish the events yet, and send a key
8755 // Injection will succeed because we will eventually give up and send the key to the focused
8756 // window even if motions are still being processed.
8757
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008758 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008759 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8760 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008762 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008763 // and the key remains pending, waiting for the touch events to be processed.
8764 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8765 // under the hood.
8766 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8767 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008768
8769 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008770 mFocusedWindow->setFocusable(false);
8771 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008772 mDispatcher->onWindowInfosChanged(
8773 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008774 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008775
8776 // Focus events should precede the key events
8777 mUnfocusedWindow->consumeFocusEvent(true);
8778 mFocusedWindow->consumeFocusEvent(false);
8779
8780 // Finish the tap events, which should unblock dispatcher
8781 mUnfocusedWindow->finishEvent(*downSequenceNum);
8782 mUnfocusedWindow->finishEvent(*upSequenceNum);
8783
8784 // Now that all queues are cleared and no backlog in the connections, the key event
8785 // can finally go to the newly focused "mUnfocusedWindow".
8786 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8787 mFocusedWindow->assertNoEvents();
8788 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008789 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008790}
8791
8792// When the touch stream is split across 2 windows, and one of them does not respond,
8793// then ANR should be raised and the touch should be canceled for the unresponsive window.
8794// The other window should not be affected by that.
8795TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8796 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008797 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8798 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8799 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008800 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008801
8802 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008803 mDispatcher->notifyMotion(
8804 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8805 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008806
8807 const std::chrono::duration timeout =
8808 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008809 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008810
8811 mUnfocusedWindow->consumeMotionDown();
8812 mFocusedWindow->consumeMotionDown();
8813 // Focused window may or may not receive ACTION_MOVE
8814 // But it should definitely receive ACTION_CANCEL due to the ANR
8815 InputEvent* event;
8816 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8817 ASSERT_TRUE(moveOrCancelSequenceNum);
8818 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8819 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008820 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008821 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8822 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8823 mFocusedWindow->consumeMotionCancel();
8824 } else {
8825 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8826 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008827 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008828 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8829 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008830
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008831 mUnfocusedWindow->assertNoEvents();
8832 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008833 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008834}
8835
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008836/**
8837 * If we have no focused window, and a key comes in, we start the ANR timer.
8838 * The focused application should add a focused window before the timer runs out to prevent ANR.
8839 *
8840 * If the user touches another application during this time, the key should be dropped.
8841 * Next, if a new focused window comes in, without toggling the focused application,
8842 * then no ANR should occur.
8843 *
8844 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8845 * but in some cases the policy may not update the focused application.
8846 */
8847TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8848 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8849 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008850 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008851 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8852 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8853 mFocusedWindow->setFocusable(false);
8854
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008855 mDispatcher->onWindowInfosChanged(
8856 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008857 mFocusedWindow->consumeFocusEvent(false);
8858
8859 // Send a key. The ANR timer should start because there is no focused window.
8860 // 'focusedApplication' will get blamed if this timer completes.
8861 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008862 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008863 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8864 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008865 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008867
8868 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8869 // then the injected touches won't cause the focused event to get dropped.
8870 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8871 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8872 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8873 // For this test, it means that the key would get delivered to the window once it becomes
8874 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008875 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008876
8877 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008878 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8879 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8880 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008881
8882 // We do not consume the motion right away, because that would require dispatcher to first
8883 // process (== drop) the key event, and by that time, ANR will be raised.
8884 // Set the focused window first.
8885 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008886 mDispatcher->onWindowInfosChanged(
8887 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008888 setFocusedWindow(mFocusedWindow);
8889 mFocusedWindow->consumeFocusEvent(true);
8890 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8891 // to another application. This could be a bug / behaviour in the policy.
8892
8893 mUnfocusedWindow->consumeMotionDown();
8894
8895 ASSERT_TRUE(mDispatcher->waitForIdle());
8896 // Should not ANR because we actually have a focused window. It was just added too slowly.
8897 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8898}
8899
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08008900/**
8901 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
8902 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
8903 * dispatcher doesn't prune pointer events incorrectly.
8904 *
8905 * This test reproduces a crash in InputDispatcher.
8906 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
8907 *
8908 * Keep the currently focused application (mApplication), and have no focused window.
8909 * We set up two additional windows:
8910 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
8911 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
8912 * window. This window is not focusable, but is touchable.
8913 *
8914 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
8915 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
8916 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
8917 *
8918 * Now, we touch "Another window". This window is owned by a different application than
8919 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
8920 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
8921 * dropping the events from its queue. Ensure that no crash occurs.
8922 *
8923 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
8924 * This does not affect the test running time.
8925 */
8926TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
8927 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
8928 std::make_shared<FakeApplicationHandle>();
8929 systemUiApplication->setDispatchingTimeout(3000ms);
8930 mFakePolicy->setStaleEventTimeout(3000ms);
8931 sp<FakeWindowHandle> navigationBar =
8932 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
8933 ADISPLAY_ID_DEFAULT);
8934 navigationBar->setFocusable(false);
8935 navigationBar->setWatchOutsideTouch(true);
8936 navigationBar->setFrame(Rect(0, 0, 100, 100));
8937
8938 mApplication->setDispatchingTimeout(3000ms);
8939 // 'mApplication' is already focused, but we call it again here to make it explicit.
8940 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8941
8942 std::shared_ptr<FakeApplicationHandle> anotherApplication =
8943 std::make_shared<FakeApplicationHandle>();
8944 sp<FakeWindowHandle> appWindow =
8945 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
8946 ADISPLAY_ID_DEFAULT);
8947 appWindow->setFocusable(false);
8948 appWindow->setFrame(Rect(100, 100, 200, 200));
8949
8950 mDispatcher->onWindowInfosChanged(
8951 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
8952 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
8953 mFocusedWindow->consumeFocusEvent(false);
8954
8955 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
8956 // in response.
8957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8958 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8959 .build());
8960 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8961
8962 // Key will not be sent anywhere because we have no focused window. It will remain pending.
8963 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
8964 InputEventInjectionResult result =
8965 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8966 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8967 /*allowKeyRepeat=*/false);
8968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8969
8970 // Finish the gesture - lift up finger and inject ACTION_UP key event
8971 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8972 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8973 .build());
8974 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8975 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8976 /*allowKeyRepeat=*/false);
8977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8978 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
8979 // getting any events yet.
8980 navigationBar->assertNoEvents();
8981
8982 // Now touch "Another window". This touch is going to a different application than the one we
8983 // are waiting for (which is 'mApplication').
8984 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
8985 // trying to be injected) and to continue processing the rest of the events in the original
8986 // order.
8987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8988 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8989 .build());
8990 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
8991 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
8992 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8993
8994 appWindow->assertNoEvents();
8995 navigationBar->assertNoEvents();
8996}
8997
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008998// These tests ensure we cannot send touch events to a window that's positioned behind a window
8999// that has feature NO_INPUT_CHANNEL.
9000// Layout:
9001// Top (closest to user)
9002// mNoInputWindow (above all windows)
9003// mBottomWindow
9004// Bottom (furthest from user)
9005class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9006 virtual void SetUp() override {
9007 InputDispatcherTest::SetUp();
9008
9009 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009010 mNoInputWindow =
9011 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9012 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009013 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009014 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009015 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9016 // It's perfectly valid for this window to not have an associated input channel
9017
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009018 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9019 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009020 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9021
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009022 mDispatcher->onWindowInfosChanged(
9023 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009024 }
9025
9026protected:
9027 std::shared_ptr<FakeApplicationHandle> mApplication;
9028 sp<FakeWindowHandle> mNoInputWindow;
9029 sp<FakeWindowHandle> mBottomWindow;
9030};
9031
9032TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9033 PointF touchedPoint = {10, 10};
9034
Prabir Pradhan678438e2023-04-13 19:32:51 +00009035 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9036 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9037 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009038
9039 mNoInputWindow->assertNoEvents();
9040 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9041 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9042 // and therefore should prevent mBottomWindow from receiving touches
9043 mBottomWindow->assertNoEvents();
9044}
9045
9046/**
9047 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9048 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9049 */
9050TEST_F(InputDispatcherMultiWindowOcclusionTests,
9051 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009052 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9053 "Window with input channel and NO_INPUT_CHANNEL",
9054 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009055
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009056 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009057 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009058 mDispatcher->onWindowInfosChanged(
9059 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009060
9061 PointF touchedPoint = {10, 10};
9062
Prabir Pradhan678438e2023-04-13 19:32:51 +00009063 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9064 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9065 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009066
9067 mNoInputWindow->assertNoEvents();
9068 mBottomWindow->assertNoEvents();
9069}
9070
Vishnu Nair958da932020-08-21 17:12:37 -07009071class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9072protected:
9073 std::shared_ptr<FakeApplicationHandle> mApp;
9074 sp<FakeWindowHandle> mWindow;
9075 sp<FakeWindowHandle> mMirror;
9076
9077 virtual void SetUp() override {
9078 InputDispatcherTest::SetUp();
9079 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009080 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009081 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009082 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9083 mWindow->setFocusable(true);
9084 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009085 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009086 }
9087};
9088
9089TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9090 // Request focus on a mirrored window
9091 setFocusedWindow(mMirror);
9092
9093 // window gets focused
9094 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009096 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009097 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9098}
9099
9100// A focused & mirrored window remains focused only if the window and its mirror are both
9101// focusable.
9102TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9103 setFocusedWindow(mMirror);
9104
9105 // window gets focused
9106 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009108 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009109 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009111 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009112 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9113
9114 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009115 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009116
9117 // window loses focus since one of the windows associated with the token in not focusable
9118 mWindow->consumeFocusEvent(false);
9119
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009120 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009121 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009122 mWindow->assertNoEvents();
9123}
9124
9125// A focused & mirrored window remains focused until the window and its mirror both become
9126// invisible.
9127TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9128 setFocusedWindow(mMirror);
9129
9130 // window gets focused
9131 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009133 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009134 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009136 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009137 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9138
9139 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009140 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009141
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009143 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009144 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009146 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009147 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9148
9149 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009150 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009151
9152 // window loses focus only after all windows associated with the token become invisible.
9153 mWindow->consumeFocusEvent(false);
9154
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009155 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009156 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009157 mWindow->assertNoEvents();
9158}
9159
9160// A focused & mirrored window remains focused until both windows are removed.
9161TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9162 setFocusedWindow(mMirror);
9163
9164 // window gets focused
9165 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009167 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009168 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009170 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009171 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9172
9173 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009174 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009175
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009177 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009178 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009180 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009181 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9182
9183 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009184 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009185 mWindow->consumeFocusEvent(false);
9186
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009187 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009188 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009189 mWindow->assertNoEvents();
9190}
9191
9192// Focus request can be pending until one window becomes visible.
9193TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9194 // Request focus on an invisible mirror.
9195 mWindow->setVisible(false);
9196 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009197 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009198 setFocusedWindow(mMirror);
9199
9200 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009202 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9203 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009204
9205 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009206 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009207
9208 // window gets focused
9209 mWindow->consumeFocusEvent(true);
9210 // window gets the pending key event
9211 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9212}
Prabir Pradhan99987712020-11-10 18:43:05 -08009213
9214class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9215protected:
9216 std::shared_ptr<FakeApplicationHandle> mApp;
9217 sp<FakeWindowHandle> mWindow;
9218 sp<FakeWindowHandle> mSecondWindow;
9219
9220 void SetUp() override {
9221 InputDispatcherTest::SetUp();
9222 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009223 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009224 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009225 mSecondWindow =
9226 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009227 mSecondWindow->setFocusable(true);
9228
9229 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009230 mDispatcher->onWindowInfosChanged(
9231 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009232
9233 setFocusedWindow(mWindow);
9234 mWindow->consumeFocusEvent(true);
9235 }
9236
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009237 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009238 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009239 }
9240
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009241 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9242 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009243 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009244 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9245 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009246 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009247 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009248 }
9249};
9250
9251TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9252 // Ensure that capture cannot be obtained for unfocused windows.
9253 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9254 mFakePolicy->assertSetPointerCaptureNotCalled();
9255 mSecondWindow->assertNoEvents();
9256
9257 // Ensure that capture can be enabled from the focus window.
9258 requestAndVerifyPointerCapture(mWindow, true);
9259
9260 // Ensure that capture cannot be disabled from a window that does not have capture.
9261 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9262 mFakePolicy->assertSetPointerCaptureNotCalled();
9263
9264 // Ensure that capture can be disabled from the window with capture.
9265 requestAndVerifyPointerCapture(mWindow, false);
9266}
9267
9268TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009269 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009270
9271 setFocusedWindow(mSecondWindow);
9272
9273 // Ensure that the capture disabled event was sent first.
9274 mWindow->consumeCaptureEvent(false);
9275 mWindow->consumeFocusEvent(false);
9276 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009277 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009278
9279 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009280 notifyPointerCaptureChanged({});
9281 notifyPointerCaptureChanged(request);
9282 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009283 mWindow->assertNoEvents();
9284 mSecondWindow->assertNoEvents();
9285 mFakePolicy->assertSetPointerCaptureNotCalled();
9286}
9287
9288TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009289 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009290
9291 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009292 notifyPointerCaptureChanged({});
9293 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009294
9295 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009296 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009297 mWindow->consumeCaptureEvent(false);
9298 mWindow->assertNoEvents();
9299}
9300
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009301TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9302 requestAndVerifyPointerCapture(mWindow, true);
9303
9304 // The first window loses focus.
9305 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009306 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009307 mWindow->consumeCaptureEvent(false);
9308
9309 // Request Pointer Capture from the second window before the notification from InputReader
9310 // arrives.
9311 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009312 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009313
9314 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009315 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009316
9317 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009318 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009319
9320 mSecondWindow->consumeFocusEvent(true);
9321 mSecondWindow->consumeCaptureEvent(true);
9322}
9323
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009324TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9325 // App repeatedly enables and disables capture.
9326 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9327 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9328 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9329 mFakePolicy->assertSetPointerCaptureCalled(false);
9330 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9331 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9332
9333 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9334 // first request is now stale, this should do nothing.
9335 notifyPointerCaptureChanged(firstRequest);
9336 mWindow->assertNoEvents();
9337
9338 // InputReader notifies that the second request was enabled.
9339 notifyPointerCaptureChanged(secondRequest);
9340 mWindow->consumeCaptureEvent(true);
9341}
9342
Prabir Pradhan7092e262022-05-03 16:51:09 +00009343TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9344 requestAndVerifyPointerCapture(mWindow, true);
9345
9346 // App toggles pointer capture off and on.
9347 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9348 mFakePolicy->assertSetPointerCaptureCalled(false);
9349
9350 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9351 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9352
9353 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9354 // preceding "disable" request.
9355 notifyPointerCaptureChanged(enableRequest);
9356
9357 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9358 // any notifications.
9359 mWindow->assertNoEvents();
9360}
9361
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009362/**
9363 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9364 * mouse movements don't affect the previous mouse hovering state.
9365 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9366 * HOVER_MOVE events).
9367 */
9368TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9369 // Mouse hover on the window
9370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9371 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9372 .build());
9373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9374 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9375 .build());
9376
9377 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9378 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9379
9380 // Start pointer capture
9381 requestAndVerifyPointerCapture(mWindow, true);
9382
9383 // Send some relative mouse movements and receive them in the window.
9384 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9385 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9386 .build());
9387 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9388 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9389
9390 // Stop pointer capture
9391 requestAndVerifyPointerCapture(mWindow, false);
9392
9393 // Continue hovering on the window
9394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9395 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9396 .build());
9397 mWindow->consumeMotionEvent(
9398 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9399
9400 mWindow->assertNoEvents();
9401}
9402
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009403class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9404protected:
9405 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009406
9407 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9408 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9409
9410 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9411 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9412
9413 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9414 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9415 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9416 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9417 MAXIMUM_OBSCURING_OPACITY);
9418
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009419 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9420 static constexpr gui::Uid APP_B_UID{10002};
9421 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009422
9423 sp<FakeWindowHandle> mTouchWindow;
9424
9425 virtual void SetUp() override {
9426 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009427 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009428 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9429 }
9430
9431 virtual void TearDown() override {
9432 InputDispatcherTest::TearDown();
9433 mTouchWindow.clear();
9434 }
9435
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009436 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009437 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009438 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009439 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009440 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009441 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009442 return window;
9443 }
9444
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009445 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009446 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9447 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009448 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009449 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009450 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009451 return window;
9452 }
9453
9454 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009455 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9456 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9457 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009458 }
9459};
9460
9461TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009462 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009463 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009464 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009465
9466 touch();
9467
9468 mTouchWindow->assertNoEvents();
9469}
9470
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009471TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009472 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9473 const sp<FakeWindowHandle>& w =
9474 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009475 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009476
9477 touch();
9478
9479 mTouchWindow->assertNoEvents();
9480}
9481
9482TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009483 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9484 const sp<FakeWindowHandle>& w =
9485 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009486 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009487
9488 touch();
9489
9490 w->assertNoEvents();
9491}
9492
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009493TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009494 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009495 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009496
9497 touch();
9498
9499 mTouchWindow->consumeAnyMotionDown();
9500}
9501
9502TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009503 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009504 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009505 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009506 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009507
9508 touch({PointF{100, 100}});
9509
9510 mTouchWindow->consumeAnyMotionDown();
9511}
9512
9513TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009514 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009515 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009516 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009517
9518 touch();
9519
9520 mTouchWindow->consumeAnyMotionDown();
9521}
9522
9523TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9524 const sp<FakeWindowHandle>& w =
9525 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009526 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009527
9528 touch();
9529
9530 mTouchWindow->consumeAnyMotionDown();
9531}
9532
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009533TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9534 const sp<FakeWindowHandle>& w =
9535 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009536 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009537
9538 touch();
9539
9540 w->assertNoEvents();
9541}
9542
9543/**
9544 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9545 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9546 * window, the occluding window will still receive ACTION_OUTSIDE event.
9547 */
9548TEST_F(InputDispatcherUntrustedTouchesTest,
9549 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9550 const sp<FakeWindowHandle>& w =
9551 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009552 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009553 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009554
9555 touch();
9556
9557 w->consumeMotionOutside();
9558}
9559
9560TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9561 const sp<FakeWindowHandle>& w =
9562 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009563 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009564 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009565
9566 touch();
9567
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009568 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009569}
9570
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009571TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009572 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009573 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9574 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009575 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009576
9577 touch();
9578
9579 mTouchWindow->consumeAnyMotionDown();
9580}
9581
9582TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9583 const sp<FakeWindowHandle>& w =
9584 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9585 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009586 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009587
9588 touch();
9589
9590 mTouchWindow->consumeAnyMotionDown();
9591}
9592
9593TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009594 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009595 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9596 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009597 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009598
9599 touch();
9600
9601 mTouchWindow->assertNoEvents();
9602}
9603
9604TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9605 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9606 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009607 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9608 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009609 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009610 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9611 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009612 mDispatcher->onWindowInfosChanged(
9613 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009614
9615 touch();
9616
9617 mTouchWindow->assertNoEvents();
9618}
9619
9620TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9621 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9622 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009623 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9624 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009625 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009626 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9627 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009628 mDispatcher->onWindowInfosChanged(
9629 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009630
9631 touch();
9632
9633 mTouchWindow->consumeAnyMotionDown();
9634}
9635
9636TEST_F(InputDispatcherUntrustedTouchesTest,
9637 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9638 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009639 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9640 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009641 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009642 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9643 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009644 mDispatcher->onWindowInfosChanged(
9645 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009646
9647 touch();
9648
9649 mTouchWindow->consumeAnyMotionDown();
9650}
9651
9652TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9653 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009654 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9655 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009656 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009657 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9658 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009659 mDispatcher->onWindowInfosChanged(
9660 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009661
9662 touch();
9663
9664 mTouchWindow->assertNoEvents();
9665}
9666
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009667TEST_F(InputDispatcherUntrustedTouchesTest,
9668 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9669 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009670 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9671 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009672 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009673 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9674 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009675 mDispatcher->onWindowInfosChanged(
9676 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009677
9678 touch();
9679
9680 mTouchWindow->assertNoEvents();
9681}
9682
9683TEST_F(InputDispatcherUntrustedTouchesTest,
9684 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9685 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009686 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9687 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009688 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009689 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9690 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009691 mDispatcher->onWindowInfosChanged(
9692 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009693
9694 touch();
9695
9696 mTouchWindow->consumeAnyMotionDown();
9697}
9698
9699TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9700 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009701 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9702 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009703 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009704
9705 touch();
9706
9707 mTouchWindow->consumeAnyMotionDown();
9708}
9709
9710TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9711 const sp<FakeWindowHandle>& w =
9712 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009713 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009714
9715 touch();
9716
9717 mTouchWindow->consumeAnyMotionDown();
9718}
9719
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009720TEST_F(InputDispatcherUntrustedTouchesTest,
9721 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9722 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9723 const sp<FakeWindowHandle>& w =
9724 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009725 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009726
9727 touch();
9728
9729 mTouchWindow->assertNoEvents();
9730}
9731
9732TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9733 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9734 const sp<FakeWindowHandle>& w =
9735 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009736 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009737
9738 touch();
9739
9740 mTouchWindow->consumeAnyMotionDown();
9741}
9742
9743TEST_F(InputDispatcherUntrustedTouchesTest,
9744 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9745 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9746 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009747 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9748 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009749 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009750
9751 touch();
9752
9753 mTouchWindow->consumeAnyMotionDown();
9754}
9755
9756TEST_F(InputDispatcherUntrustedTouchesTest,
9757 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9758 const sp<FakeWindowHandle>& w1 =
9759 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9760 OPACITY_BELOW_THRESHOLD);
9761 const sp<FakeWindowHandle>& w2 =
9762 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9763 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009764 mDispatcher->onWindowInfosChanged(
9765 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009766
9767 touch();
9768
9769 mTouchWindow->assertNoEvents();
9770}
9771
9772/**
9773 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9774 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9775 * (which alone would result in allowing touches) does not affect the blocking behavior.
9776 */
9777TEST_F(InputDispatcherUntrustedTouchesTest,
9778 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9779 const sp<FakeWindowHandle>& wB =
9780 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9781 OPACITY_BELOW_THRESHOLD);
9782 const sp<FakeWindowHandle>& wC =
9783 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9784 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009785 mDispatcher->onWindowInfosChanged(
9786 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009787
9788 touch();
9789
9790 mTouchWindow->assertNoEvents();
9791}
9792
9793/**
9794 * This test is testing that a window from a different UID but with same application token doesn't
9795 * block the touch. Apps can share the application token for close UI collaboration for example.
9796 */
9797TEST_F(InputDispatcherUntrustedTouchesTest,
9798 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9799 const sp<FakeWindowHandle>& w =
9800 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9801 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009802 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009803
9804 touch();
9805
9806 mTouchWindow->consumeAnyMotionDown();
9807}
9808
arthurhungb89ccb02020-12-30 16:19:01 +08009809class InputDispatcherDragTests : public InputDispatcherTest {
9810protected:
9811 std::shared_ptr<FakeApplicationHandle> mApp;
9812 sp<FakeWindowHandle> mWindow;
9813 sp<FakeWindowHandle> mSecondWindow;
9814 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009815 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009816 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9817 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009818
9819 void SetUp() override {
9820 InputDispatcherTest::SetUp();
9821 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009822 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009823 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009824
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009825 mSecondWindow =
9826 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009827 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009828
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009829 mSpyWindow =
9830 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009831 mSpyWindow->setSpy(true);
9832 mSpyWindow->setTrustedOverlay(true);
9833 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9834
arthurhungb89ccb02020-12-30 16:19:01 +08009835 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009836 mDispatcher->onWindowInfosChanged(
9837 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9838 {},
9839 0,
9840 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009841 }
9842
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009843 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9844 switch (fromSource) {
9845 case AINPUT_SOURCE_TOUCHSCREEN:
9846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009847 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009848 ADISPLAY_ID_DEFAULT, {50, 50}))
9849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9850 break;
9851 case AINPUT_SOURCE_STYLUS:
9852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009853 injectMotionEvent(*mDispatcher,
9854 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9855 AINPUT_SOURCE_STYLUS)
9856 .buttonState(
9857 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9858 .pointer(PointerBuilder(0, ToolType::STYLUS)
9859 .x(50)
9860 .y(50))
9861 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009862 break;
9863 case AINPUT_SOURCE_MOUSE:
9864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009865 injectMotionEvent(*mDispatcher,
9866 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9867 AINPUT_SOURCE_MOUSE)
9868 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9869 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9870 ToolType::MOUSE)
9871 .x(50)
9872 .y(50))
9873 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009874 break;
9875 default:
9876 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9877 }
arthurhungb89ccb02020-12-30 16:19:01 +08009878
9879 // Window should receive motion event.
9880 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009881 // Spy window should also receive motion event
9882 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009883 }
9884
9885 // Start performing drag, we will create a drag window and transfer touch to it.
9886 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9887 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009888 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009889 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009890 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009891 }
arthurhungb89ccb02020-12-30 16:19:01 +08009892
9893 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009894 mDragWindow =
9895 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009896 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009897 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9898 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9899 {},
9900 0,
9901 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009902
9903 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009904 bool transferred =
9905 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009906 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009907 if (transferred) {
9908 mWindow->consumeMotionCancel();
9909 mDragWindow->consumeMotionDown();
9910 }
9911 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009912 }
9913};
9914
9915TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009916 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009917
9918 // Move on window.
9919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009920 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009921 ADISPLAY_ID_DEFAULT, {50, 50}))
9922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9923 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9924 mWindow->consumeDragEvent(false, 50, 50);
9925 mSecondWindow->assertNoEvents();
9926
9927 // Move to another window.
9928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009929 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009930 ADISPLAY_ID_DEFAULT, {150, 50}))
9931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9932 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9933 mWindow->consumeDragEvent(true, 150, 50);
9934 mSecondWindow->consumeDragEvent(false, 50, 50);
9935
9936 // Move back to original window.
9937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009938 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009939 ADISPLAY_ID_DEFAULT, {50, 50}))
9940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9941 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9942 mWindow->consumeDragEvent(false, 50, 50);
9943 mSecondWindow->consumeDragEvent(true, -50, 50);
9944
9945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009946 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9947 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009948 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9949 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9950 mWindow->assertNoEvents();
9951 mSecondWindow->assertNoEvents();
9952}
9953
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009954TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009955 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009956
9957 // No cancel event after drag start
9958 mSpyWindow->assertNoEvents();
9959
9960 const MotionEvent secondFingerDownEvent =
9961 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9962 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009963 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9964 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009965 .build();
9966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009967 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009968 InputEventInjectionSync::WAIT_FOR_RESULT))
9969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9970
9971 // Receives cancel for first pointer after next pointer down
9972 mSpyWindow->consumeMotionCancel();
9973 mSpyWindow->consumeMotionDown();
9974
9975 mSpyWindow->assertNoEvents();
9976}
9977
arthurhungf452d0b2021-01-06 00:19:52 +08009978TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009979 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009980
9981 // Move on window.
9982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009983 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009984 ADISPLAY_ID_DEFAULT, {50, 50}))
9985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9986 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9987 mWindow->consumeDragEvent(false, 50, 50);
9988 mSecondWindow->assertNoEvents();
9989
9990 // Move to another window.
9991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009992 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009993 ADISPLAY_ID_DEFAULT, {150, 50}))
9994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9995 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9996 mWindow->consumeDragEvent(true, 150, 50);
9997 mSecondWindow->consumeDragEvent(false, 50, 50);
9998
9999 // drop to another window.
10000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010001 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010002 {150, 50}))
10003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10004 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010005 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010006 mWindow->assertNoEvents();
10007 mSecondWindow->assertNoEvents();
10008}
10009
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010010TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10011 startDrag();
10012
10013 // No cancel event after drag start
10014 mSpyWindow->assertNoEvents();
10015
10016 const MotionEvent secondFingerDownEvent =
10017 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10018 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10019 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10020 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10021 .build();
10022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10023 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10024 InputEventInjectionSync::WAIT_FOR_RESULT))
10025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10026
10027 // Receives cancel for first pointer after next pointer down
10028 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010029 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010030 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10031
10032 mSpyWindow->assertNoEvents();
10033
10034 // Spy window calls pilfer pointers
10035 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10036 mDragWindow->assertNoEvents();
10037
10038 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010039 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010040 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10041 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10042 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10043 .build();
10044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010045 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010046 InputEventInjectionSync::WAIT_FOR_RESULT))
10047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10048
10049 // Drag window should still receive the new event
10050 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10051 mDragWindow->assertNoEvents();
10052}
10053
arthurhung6d4bed92021-03-17 11:59:33 +080010054TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010055 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010056
10057 // Move on window and keep button pressed.
10058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010059 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010060 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10061 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010062 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010063 .build()))
10064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10065 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10066 mWindow->consumeDragEvent(false, 50, 50);
10067 mSecondWindow->assertNoEvents();
10068
10069 // Move to another window and release button, expect to drop item.
10070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010071 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010072 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10073 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010074 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010075 .build()))
10076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10077 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10078 mWindow->assertNoEvents();
10079 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010080 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010081
10082 // nothing to the window.
10083 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010084 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010085 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10086 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010087 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010088 .build()))
10089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10090 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10091 mWindow->assertNoEvents();
10092 mSecondWindow->assertNoEvents();
10093}
10094
Arthur Hung54745652022-04-20 07:17:41 +000010095TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010096 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010097
10098 // Set second window invisible.
10099 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010100 mDispatcher->onWindowInfosChanged(
10101 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010102
10103 // Move on window.
10104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010105 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010106 ADISPLAY_ID_DEFAULT, {50, 50}))
10107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10108 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10109 mWindow->consumeDragEvent(false, 50, 50);
10110 mSecondWindow->assertNoEvents();
10111
10112 // Move to another window.
10113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010114 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010115 ADISPLAY_ID_DEFAULT, {150, 50}))
10116 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10117 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10118 mWindow->consumeDragEvent(true, 150, 50);
10119 mSecondWindow->assertNoEvents();
10120
10121 // drop to another window.
10122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010123 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010124 {150, 50}))
10125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10126 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010127 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010128 mWindow->assertNoEvents();
10129 mSecondWindow->assertNoEvents();
10130}
10131
Arthur Hung54745652022-04-20 07:17:41 +000010132TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010133 // Ensure window could track pointerIds if it didn't support split touch.
10134 mWindow->setPreventSplitting(true);
10135
Arthur Hung54745652022-04-20 07:17:41 +000010136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010137 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010138 {50, 50}))
10139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10140 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10141
10142 const MotionEvent secondFingerDownEvent =
10143 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10144 .displayId(ADISPLAY_ID_DEFAULT)
10145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010146 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10147 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010148 .build();
10149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010150 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010151 InputEventInjectionSync::WAIT_FOR_RESULT))
10152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010153 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010154
10155 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010156 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010157}
10158
10159TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10160 // First down on second window.
10161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010162 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010163 {150, 50}))
10164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10165
10166 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10167
10168 // Second down on first window.
10169 const MotionEvent secondFingerDownEvent =
10170 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10171 .displayId(ADISPLAY_ID_DEFAULT)
10172 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010173 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10174 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010175 .build();
10176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010177 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010178 InputEventInjectionSync::WAIT_FOR_RESULT))
10179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10180 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10181
10182 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010183 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010184
10185 // Move on window.
10186 const MotionEvent secondFingerMoveEvent =
10187 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10188 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010189 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10190 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010191 .build();
10192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010193 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010194 InputEventInjectionSync::WAIT_FOR_RESULT));
10195 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10196 mWindow->consumeDragEvent(false, 50, 50);
10197 mSecondWindow->consumeMotionMove();
10198
10199 // Release the drag pointer should perform drop.
10200 const MotionEvent secondFingerUpEvent =
10201 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10202 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010203 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10204 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010205 .build();
10206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010207 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010208 InputEventInjectionSync::WAIT_FOR_RESULT));
10209 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010210 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010211 mWindow->assertNoEvents();
10212 mSecondWindow->consumeMotionMove();
10213}
10214
Arthur Hung3915c1f2022-05-31 07:17:17 +000010215TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010216 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010217
10218 // Update window of second display.
10219 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010220 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010221 mDispatcher->onWindowInfosChanged(
10222 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10223 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10224 {},
10225 0,
10226 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010227
10228 // Let second display has a touch state.
10229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010230 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010231 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10232 AINPUT_SOURCE_TOUCHSCREEN)
10233 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010234 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010235 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010236 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010237 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010238 mDispatcher->onWindowInfosChanged(
10239 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10240 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10241 {},
10242 0,
10243 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010244
10245 // Move on window.
10246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010247 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010248 ADISPLAY_ID_DEFAULT, {50, 50}))
10249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10250 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10251 mWindow->consumeDragEvent(false, 50, 50);
10252 mSecondWindow->assertNoEvents();
10253
10254 // Move to another window.
10255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010256 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010257 ADISPLAY_ID_DEFAULT, {150, 50}))
10258 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10259 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10260 mWindow->consumeDragEvent(true, 150, 50);
10261 mSecondWindow->consumeDragEvent(false, 50, 50);
10262
10263 // drop to another window.
10264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010265 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010266 {150, 50}))
10267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10268 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010269 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010270 mWindow->assertNoEvents();
10271 mSecondWindow->assertNoEvents();
10272}
10273
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010274TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10275 startDrag(true, AINPUT_SOURCE_MOUSE);
10276 // Move on window.
10277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010278 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010279 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10280 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010281 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010282 .x(50)
10283 .y(50))
10284 .build()))
10285 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10286 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10287 mWindow->consumeDragEvent(false, 50, 50);
10288 mSecondWindow->assertNoEvents();
10289
10290 // Move to another window.
10291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010292 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010293 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10294 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010295 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010296 .x(150)
10297 .y(50))
10298 .build()))
10299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10300 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10301 mWindow->consumeDragEvent(true, 150, 50);
10302 mSecondWindow->consumeDragEvent(false, 50, 50);
10303
10304 // drop to another window.
10305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010306 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010307 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10308 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010309 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010310 .x(150)
10311 .y(50))
10312 .build()))
10313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10314 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010315 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010316 mWindow->assertNoEvents();
10317 mSecondWindow->assertNoEvents();
10318}
10319
Linnan Li5af92f92023-07-14 14:36:22 +080010320/**
10321 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10322 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10323 */
10324TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10325 // Down on second window
10326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10327 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10328 {150, 50}))
10329 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10330
10331 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10332 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10333
10334 // Down on first window
10335 const MotionEvent secondFingerDownEvent =
10336 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10337 .displayId(ADISPLAY_ID_DEFAULT)
10338 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10339 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10340 .build();
10341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10342 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10343 InputEventInjectionSync::WAIT_FOR_RESULT))
10344 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10345 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10346 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10347 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10348
10349 // Start drag on first window
10350 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10351
10352 // Trigger cancel
10353 mDispatcher->cancelCurrentTouch();
10354 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10355 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10356 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10357
10358 ASSERT_TRUE(mDispatcher->waitForIdle());
10359 // The D&D finished with nullptr
10360 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10361
10362 // Remove drag window
10363 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10364
10365 // Inject a simple gesture, ensure dispatcher not crashed
10366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10367 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10368 PointF{50, 50}))
10369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10370 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10371
10372 const MotionEvent moveEvent =
10373 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10374 .displayId(ADISPLAY_ID_DEFAULT)
10375 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10376 .build();
10377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10378 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10379 InputEventInjectionSync::WAIT_FOR_RESULT))
10380 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10381 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10382
10383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10384 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10385 {50, 50}))
10386 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10387 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10388}
10389
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010390TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10391 // Start hovering over the window.
10392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10393 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10394 ADISPLAY_ID_DEFAULT, {50, 50}));
10395
10396 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10397 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10398
10399 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10400 << "Drag and drop should not work with a hovering pointer";
10401}
10402
Vishnu Nair062a8672021-09-03 16:07:44 -070010403class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10404
10405TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010407 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10408 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010409 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010410 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10411 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010412 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010413 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010414 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010415
10416 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010417 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010418 window->assertNoEvents();
10419
Prabir Pradhan678438e2023-04-13 19:32:51 +000010420 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10421 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10423 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010424 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010425 window->assertNoEvents();
10426
10427 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010428 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010429 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010430
Prabir Pradhan678438e2023-04-13 19:32:51 +000010431 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010432 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10433
Prabir Pradhan678438e2023-04-13 19:32:51 +000010434 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10435 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010436 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10437 window->assertNoEvents();
10438}
10439
10440TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10441 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10442 std::make_shared<FakeApplicationHandle>();
10443 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010444 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10445 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010446 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010447 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010448 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010450 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10451 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010452 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010453 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010454 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10455 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010456 mDispatcher->onWindowInfosChanged(
10457 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010458 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010459 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010460
10461 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010462 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010463 window->assertNoEvents();
10464
Prabir Pradhan678438e2023-04-13 19:32:51 +000010465 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10466 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010467 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10468 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010469 window->assertNoEvents();
10470
10471 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010472 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010473 mDispatcher->onWindowInfosChanged(
10474 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010475
Prabir Pradhan678438e2023-04-13 19:32:51 +000010476 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010477 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10478
Prabir Pradhan678438e2023-04-13 19:32:51 +000010479 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10480 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010481 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10482 window->assertNoEvents();
10483}
10484
10485TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10486 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10487 std::make_shared<FakeApplicationHandle>();
10488 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010489 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10490 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010491 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010492 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010493 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010495 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10496 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010497 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010498 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010499 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10500 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010501 mDispatcher->onWindowInfosChanged(
10502 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010503 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010504 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010505
10506 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010507 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010508 window->assertNoEvents();
10509
Prabir Pradhan678438e2023-04-13 19:32:51 +000010510 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10511 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10513 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010514 window->assertNoEvents();
10515
10516 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010517 mDispatcher->onWindowInfosChanged(
10518 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010519
Prabir Pradhan678438e2023-04-13 19:32:51 +000010520 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010521 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10522
Prabir Pradhan678438e2023-04-13 19:32:51 +000010523 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10524 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010525 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10526 window->assertNoEvents();
10527}
10528
Antonio Kantekf16f2832021-09-28 04:39:20 +000010529class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10530protected:
10531 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010532 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010533 sp<FakeWindowHandle> mWindow;
10534 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010535 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010536
10537 void SetUp() override {
10538 InputDispatcherTest::SetUp();
10539
10540 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010541 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010542 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010543 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010544 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010545 mSecondWindow =
10546 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010547 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010548 mThirdWindow =
10549 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10550 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10551 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010552
10553 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010554 mDispatcher->onWindowInfosChanged(
10555 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10556 {},
10557 0,
10558 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010559 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010560 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010561
Antonio Kantek15beb512022-06-13 22:35:41 +000010562 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010563 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010564 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010565 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10566 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010567 mThirdWindow->assertNoEvents();
10568 }
10569
10570 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10571 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010572 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010573 SECOND_DISPLAY_ID)) {
10574 mWindow->assertNoEvents();
10575 mSecondWindow->assertNoEvents();
10576 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010577 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010578 }
10579
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010580 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010581 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010582 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10583 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010584 mWindow->consumeTouchModeEvent(inTouchMode);
10585 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010586 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010587 }
10588};
10589
Antonio Kantek26defcf2022-02-08 01:12:27 +000010590TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010591 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010592 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10593 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010594 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010595}
10596
Antonio Kantek26defcf2022-02-08 01:12:27 +000010597TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10598 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010599 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010600 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010601 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010602 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010603 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010604 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010605 mWindow->assertNoEvents();
10606 mSecondWindow->assertNoEvents();
10607}
10608
10609TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10610 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010611 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010612 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010613 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010614 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010615 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010616}
10617
Antonio Kantekf16f2832021-09-28 04:39:20 +000010618TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010619 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010620 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10621 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010622 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010623 mWindow->assertNoEvents();
10624 mSecondWindow->assertNoEvents();
10625}
10626
Antonio Kantek15beb512022-06-13 22:35:41 +000010627TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10628 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10629 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10630 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010631 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010632 mWindow->assertNoEvents();
10633 mSecondWindow->assertNoEvents();
10634 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10635}
10636
Antonio Kantek48710e42022-03-24 14:19:30 -070010637TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10638 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10640 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010641 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10642 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10643
10644 // Then remove focus.
10645 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010646 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010647
10648 // Assert that caller can switch touch mode by owning one of the last interacted window.
10649 const WindowInfo& windowInfo = *mWindow->getInfo();
10650 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10651 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010652 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010653}
10654
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010655class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10656public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010657 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010658 std::shared_ptr<FakeApplicationHandle> application =
10659 std::make_shared<FakeApplicationHandle>();
10660 std::string name = "Fake Spy ";
10661 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010662 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10663 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010664 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010665 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010666 return spy;
10667 }
10668
10669 sp<FakeWindowHandle> createForeground() {
10670 std::shared_ptr<FakeApplicationHandle> application =
10671 std::make_shared<FakeApplicationHandle>();
10672 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010673 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10674 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010675 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010676 return window;
10677 }
10678
10679private:
10680 int mSpyCount{0};
10681};
10682
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010683using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010684/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010685 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10686 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010687TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010688 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010689 ScopedSilentDeath _silentDeath;
10690
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010691 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010692 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010693 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010694 ".* not a trusted overlay");
10695}
10696
10697/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010698 * Input injection into a display with a spy window but no foreground windows should succeed.
10699 */
10700TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010701 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010702 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010703
10704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010705 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10707 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10708}
10709
10710/**
10711 * Verify the order in which different input windows receive events. The touched foreground window
10712 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10713 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10714 * receive events before ones belows it.
10715 *
10716 * Here, we set up a scenario with four windows in the following Z order from the top:
10717 * spy1, spy2, window, spy3.
10718 * We then inject an event and verify that the foreground "window" receives it first, followed by
10719 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10720 * window.
10721 */
10722TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10723 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010724 auto spy1 = createSpy();
10725 auto spy2 = createSpy();
10726 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010727 mDispatcher->onWindowInfosChanged(
10728 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010729 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10730 const size_t numChannels = channels.size();
10731
Michael Wright8e9a8562022-02-09 13:44:29 +000010732 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010733 if (!epollFd.ok()) {
10734 FAIL() << "Failed to create epoll fd";
10735 }
10736
10737 for (size_t i = 0; i < numChannels; i++) {
10738 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10739 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10740 FAIL() << "Failed to add fd to epoll";
10741 }
10742 }
10743
10744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010745 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10747
10748 std::vector<size_t> eventOrder;
10749 std::vector<struct epoll_event> events(numChannels);
10750 for (;;) {
10751 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10752 (100ms).count());
10753 if (nFds < 0) {
10754 FAIL() << "Failed to call epoll_wait";
10755 }
10756 if (nFds == 0) {
10757 break; // epoll_wait timed out
10758 }
10759 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010760 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010761 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010762 channels[i]->consumeMotionDown();
10763 }
10764 }
10765
10766 // Verify the order in which the events were received.
10767 EXPECT_EQ(3u, eventOrder.size());
10768 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10769 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10770 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10771}
10772
10773/**
10774 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10775 */
10776TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10777 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010778 auto spy = createSpy();
10779 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010780 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010781
10782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010783 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10785 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10786 spy->assertNoEvents();
10787}
10788
10789/**
10790 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10791 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10792 * to the window.
10793 */
10794TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10795 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010796 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010797 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010798 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010799
10800 // Inject an event outside the spy window's touchable region.
10801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010802 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10804 window->consumeMotionDown();
10805 spy->assertNoEvents();
10806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010807 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10809 window->consumeMotionUp();
10810 spy->assertNoEvents();
10811
10812 // Inject an event inside the spy window's touchable region.
10813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010814 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010815 {5, 10}))
10816 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10817 window->consumeMotionDown();
10818 spy->consumeMotionDown();
10819}
10820
10821/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010822 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010823 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010824 */
10825TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10826 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010827 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010828 auto spy = createSpy();
10829 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010830 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010831 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010832 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010833
10834 // Inject an event outside the spy window's frame and touchable region.
10835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010837 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10839 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010840 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010841}
10842
10843/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010844 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10845 * pointers that are down within its bounds.
10846 */
10847TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10848 auto windowLeft = createForeground();
10849 windowLeft->setFrame({0, 0, 100, 200});
10850 auto windowRight = createForeground();
10851 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010852 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010853 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010854 mDispatcher->onWindowInfosChanged(
10855 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010856
10857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010859 {50, 50}))
10860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10861 windowLeft->consumeMotionDown();
10862 spy->consumeMotionDown();
10863
10864 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010865 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010866 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010867 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10868 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010869 .build();
10870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010871 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010872 InputEventInjectionSync::WAIT_FOR_RESULT))
10873 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10874 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010875 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010876}
10877
10878/**
10879 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10880 * the spy should receive the second pointer with ACTION_DOWN.
10881 */
10882TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10883 auto window = createForeground();
10884 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010885 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010886 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010887 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010888
10889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010890 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010891 {50, 50}))
10892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10893 window->consumeMotionDown();
10894 spyRight->assertNoEvents();
10895
10896 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010897 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010898 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010899 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10900 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010901 .build();
10902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010903 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010904 InputEventInjectionSync::WAIT_FOR_RESULT))
10905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010906 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010907 spyRight->consumeMotionDown();
10908}
10909
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010910/**
10911 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10912 * windows should be allowed to control split touch.
10913 */
10914TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010915 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010916 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010917 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010918 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010919
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010920 auto window = createForeground();
10921 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010922
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010923 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010924
10925 // First finger down, no window touched.
10926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010927 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010928 {100, 200}))
10929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10930 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10931 window->assertNoEvents();
10932
10933 // Second finger down on window, the window should receive touch down.
10934 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010935 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010936 .displayId(ADISPLAY_ID_DEFAULT)
10937 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010938 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10939 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010940 .build();
10941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010942 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010943 InputEventInjectionSync::WAIT_FOR_RESULT))
10944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10945
10946 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010947 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010948}
10949
10950/**
10951 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10952 * do not receive key events.
10953 */
10954TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010955 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010956 spy->setFocusable(false);
10957
10958 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010959 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010960 setFocusedWindow(window);
10961 window->consumeFocusEvent(true);
10962
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010964 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10965 window->consumeKeyDown(ADISPLAY_ID_NONE);
10966
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010968 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10969 window->consumeKeyUp(ADISPLAY_ID_NONE);
10970
10971 spy->assertNoEvents();
10972}
10973
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010974using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10975
10976/**
10977 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10978 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10979 */
10980TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10981 auto window = createForeground();
10982 auto spy1 = createSpy();
10983 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010984 mDispatcher->onWindowInfosChanged(
10985 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010986
10987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010988 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10990 window->consumeMotionDown();
10991 spy1->consumeMotionDown();
10992 spy2->consumeMotionDown();
10993
10994 // Pilfer pointers from the second spy window.
10995 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10996 spy2->assertNoEvents();
10997 spy1->consumeMotionCancel();
10998 window->consumeMotionCancel();
10999
11000 // The rest of the gesture should only be sent to the second spy window.
11001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011002 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011003 ADISPLAY_ID_DEFAULT))
11004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11005 spy2->consumeMotionMove();
11006 spy1->assertNoEvents();
11007 window->assertNoEvents();
11008}
11009
11010/**
11011 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11012 * in the middle of the gesture.
11013 */
11014TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11015 auto window = createForeground();
11016 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011017 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011018
11019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011020 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11022 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11023 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11024
11025 window->releaseChannel();
11026
11027 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11028
11029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011030 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11032 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11033}
11034
11035/**
11036 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11037 * the spy, but not to any other windows.
11038 */
11039TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11040 auto spy = createSpy();
11041 auto window = createForeground();
11042
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011043 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011044
11045 // First finger down on the window and the spy.
11046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011047 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011048 {100, 200}))
11049 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11050 spy->consumeMotionDown();
11051 window->consumeMotionDown();
11052
11053 // Spy window pilfers the pointers.
11054 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11055 window->consumeMotionCancel();
11056
11057 // Second finger down on the window and spy, but the window should not receive the pointer down.
11058 const MotionEvent secondFingerDownEvent =
11059 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11060 .displayId(ADISPLAY_ID_DEFAULT)
11061 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011062 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11063 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011064 .build();
11065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011066 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011067 InputEventInjectionSync::WAIT_FOR_RESULT))
11068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11069
Harry Cutts33476232023-01-30 19:57:29 +000011070 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011071
11072 // Third finger goes down outside all windows, so injection should fail.
11073 const MotionEvent thirdFingerDownEvent =
11074 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11075 .displayId(ADISPLAY_ID_DEFAULT)
11076 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011077 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11078 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11079 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011080 .build();
11081 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011082 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011083 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011084 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011085
11086 spy->assertNoEvents();
11087 window->assertNoEvents();
11088}
11089
11090/**
11091 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11092 */
11093TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11094 auto spy = createSpy();
11095 spy->setFrame(Rect(0, 0, 100, 100));
11096 auto window = createForeground();
11097 window->setFrame(Rect(0, 0, 200, 200));
11098
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011099 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011100
11101 // First finger down on the window only
11102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011103 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011104 {150, 150}))
11105 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11106 window->consumeMotionDown();
11107
11108 // Second finger down on the spy and window
11109 const MotionEvent secondFingerDownEvent =
11110 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11111 .displayId(ADISPLAY_ID_DEFAULT)
11112 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011113 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11114 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011115 .build();
11116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011117 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011118 InputEventInjectionSync::WAIT_FOR_RESULT))
11119 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11120 spy->consumeMotionDown();
11121 window->consumeMotionPointerDown(1);
11122
11123 // Third finger down on the spy and window
11124 const MotionEvent thirdFingerDownEvent =
11125 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11126 .displayId(ADISPLAY_ID_DEFAULT)
11127 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011128 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11129 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11130 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011131 .build();
11132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011133 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011134 InputEventInjectionSync::WAIT_FOR_RESULT))
11135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11136 spy->consumeMotionPointerDown(1);
11137 window->consumeMotionPointerDown(2);
11138
11139 // Spy window pilfers the pointers.
11140 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011141 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11142 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011143
11144 spy->assertNoEvents();
11145 window->assertNoEvents();
11146}
11147
11148/**
11149 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11150 * other windows should be canceled. If this results in the cancellation of all pointers for some
11151 * window, then that window should receive ACTION_CANCEL.
11152 */
11153TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11154 auto spy = createSpy();
11155 spy->setFrame(Rect(0, 0, 100, 100));
11156 auto window = createForeground();
11157 window->setFrame(Rect(0, 0, 200, 200));
11158
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011159 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011160
11161 // First finger down on both spy and window
11162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011163 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011164 {10, 10}))
11165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11166 window->consumeMotionDown();
11167 spy->consumeMotionDown();
11168
11169 // Second finger down on the spy and window
11170 const MotionEvent secondFingerDownEvent =
11171 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11172 .displayId(ADISPLAY_ID_DEFAULT)
11173 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011174 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11175 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011176 .build();
11177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011178 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011179 InputEventInjectionSync::WAIT_FOR_RESULT))
11180 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11181 spy->consumeMotionPointerDown(1);
11182 window->consumeMotionPointerDown(1);
11183
11184 // Spy window pilfers the pointers.
11185 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11186 window->consumeMotionCancel();
11187
11188 spy->assertNoEvents();
11189 window->assertNoEvents();
11190}
11191
11192/**
11193 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11194 * be sent to other windows
11195 */
11196TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11197 auto spy = createSpy();
11198 spy->setFrame(Rect(0, 0, 100, 100));
11199 auto window = createForeground();
11200 window->setFrame(Rect(0, 0, 200, 200));
11201
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011202 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011203
11204 // First finger down on both window and spy
11205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011206 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011207 {10, 10}))
11208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11209 window->consumeMotionDown();
11210 spy->consumeMotionDown();
11211
11212 // Spy window pilfers the pointers.
11213 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11214 window->consumeMotionCancel();
11215
11216 // Second finger down on the window only
11217 const MotionEvent secondFingerDownEvent =
11218 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11219 .displayId(ADISPLAY_ID_DEFAULT)
11220 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011221 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11222 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011223 .build();
11224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011225 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011226 InputEventInjectionSync::WAIT_FOR_RESULT))
11227 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11228 window->consumeMotionDown();
11229 window->assertNoEvents();
11230
11231 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11232 spy->consumeMotionMove();
11233 spy->assertNoEvents();
11234}
11235
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011236/**
11237 * A window on the left and a window on the right. Also, a spy window that's above all of the
11238 * windows, and spanning both left and right windows.
11239 * Send simultaneous motion streams from two different devices, one to the left window, and another
11240 * to the right window.
11241 * Pilfer from spy window.
11242 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11243 */
11244TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11245 sp<FakeWindowHandle> spy = createSpy();
11246 spy->setFrame(Rect(0, 0, 200, 200));
11247 sp<FakeWindowHandle> leftWindow = createForeground();
11248 leftWindow->setFrame(Rect(0, 0, 100, 100));
11249
11250 sp<FakeWindowHandle> rightWindow = createForeground();
11251 rightWindow->setFrame(Rect(100, 0, 200, 100));
11252
11253 constexpr int32_t stylusDeviceId = 1;
11254 constexpr int32_t touchDeviceId = 2;
11255
11256 mDispatcher->onWindowInfosChanged(
11257 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11258
11259 // Stylus down on left window and spy
11260 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11261 .deviceId(stylusDeviceId)
11262 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11263 .build());
11264 leftWindow->consumeMotionEvent(
11265 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11266 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11267
11268 // Finger down on right window and spy - but spy already has stylus
11269 mDispatcher->notifyMotion(
11270 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11271 .deviceId(touchDeviceId)
11272 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11273 .build());
11274 rightWindow->consumeMotionEvent(
11275 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011276 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011277
11278 // Act: pilfer from spy. Spy is currently receiving touch events.
11279 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011280 leftWindow->consumeMotionEvent(
11281 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011282 rightWindow->consumeMotionEvent(
11283 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11284
11285 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11286 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11287 .deviceId(stylusDeviceId)
11288 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11289 .build());
11290 mDispatcher->notifyMotion(
11291 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11292 .deviceId(touchDeviceId)
11293 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11294 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011295 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011296
11297 spy->assertNoEvents();
11298 leftWindow->assertNoEvents();
11299 rightWindow->assertNoEvents();
11300}
11301
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011302TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11303 auto window = createForeground();
11304 auto spy = createSpy();
11305 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11306
11307 mDispatcher->notifyMotion(
11308 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11309 .deviceId(1)
11310 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11311 .build());
11312 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11313 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11314
11315 // Pilfer pointers from the spy window should fail.
11316 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11317 spy->assertNoEvents();
11318 window->assertNoEvents();
11319}
11320
Prabir Pradhand65552b2021-10-07 11:23:50 -070011321class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11322public:
11323 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11324 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11325 std::make_shared<FakeApplicationHandle>();
11326 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011327 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11328 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011329 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011330 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011331 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011332 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011333 overlay->setTrustedOverlay(true);
11334
11335 std::shared_ptr<FakeApplicationHandle> application =
11336 std::make_shared<FakeApplicationHandle>();
11337 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011338 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11339 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011340 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011341 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011342
11343 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011344 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011345 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011346 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011347 return {std::move(overlay), std::move(window)};
11348 }
11349
11350 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011351 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011352 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011353 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011354 }
11355
11356 void sendStylusEvent(int32_t action) {
11357 NotifyMotionArgs motionArgs =
11358 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11359 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011360 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011361 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011362 }
11363};
11364
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011365using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11366
11367TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011368 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011369 ScopedSilentDeath _silentDeath;
11370
Prabir Pradhand65552b2021-10-07 11:23:50 -070011371 auto [overlay, window] = setupStylusOverlayScenario();
11372 overlay->setTrustedOverlay(false);
11373 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011374 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11375 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011376 ".* not a trusted overlay");
11377}
11378
11379TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11380 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011381 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011382
11383 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11384 overlay->consumeMotionDown();
11385 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11386 overlay->consumeMotionUp();
11387
11388 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11389 window->consumeMotionDown();
11390 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11391 window->consumeMotionUp();
11392
11393 overlay->assertNoEvents();
11394 window->assertNoEvents();
11395}
11396
11397TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11398 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011399 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011400 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011401
11402 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11403 overlay->consumeMotionDown();
11404 window->consumeMotionDown();
11405 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11406 overlay->consumeMotionUp();
11407 window->consumeMotionUp();
11408
11409 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11410 window->consumeMotionDown();
11411 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11412 window->consumeMotionUp();
11413
11414 overlay->assertNoEvents();
11415 window->assertNoEvents();
11416}
11417
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011418/**
11419 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11420 * The scenario is as follows:
11421 * - The stylus interceptor overlay is configured as a spy window.
11422 * - The stylus interceptor spy receives the start of a new stylus gesture.
11423 * - It pilfers pointers and then configures itself to no longer be a spy.
11424 * - The stylus interceptor continues to receive the rest of the gesture.
11425 */
11426TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11427 auto [overlay, window] = setupStylusOverlayScenario();
11428 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011429 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011430
11431 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11432 overlay->consumeMotionDown();
11433 window->consumeMotionDown();
11434
11435 // The interceptor pilfers the pointers.
11436 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11437 window->consumeMotionCancel();
11438
11439 // The interceptor configures itself so that it is no longer a spy.
11440 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011441 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011442
11443 // It continues to receive the rest of the stylus gesture.
11444 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11445 overlay->consumeMotionMove();
11446 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11447 overlay->consumeMotionUp();
11448
11449 window->assertNoEvents();
11450}
11451
Prabir Pradhan5735a322022-04-11 17:23:34 +000011452struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011453 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011454 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011455 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11456 std::unique_ptr<InputDispatcher>& mDispatcher;
11457
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011458 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011459 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11460
11461 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011462 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011463 ADISPLAY_ID_DEFAULT, {100, 200},
11464 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11465 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11466 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11467 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11468 }
11469
11470 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011471 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011472 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011473 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011474 mPolicyFlags);
11475 }
11476
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011477 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011478 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11479 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011480 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11481 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011482 window->setOwnerInfo(mPid, mUid);
11483 return window;
11484 }
11485};
11486
11487using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11488
11489TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011490 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011491 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011492 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011493
11494 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11495 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11496 window->consumeMotionDown();
11497
11498 setFocusedWindow(window);
11499 window->consumeFocusEvent(true);
11500
11501 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11502 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11503 window->consumeKeyDown(ADISPLAY_ID_NONE);
11504}
11505
11506TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011507 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011508 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011509 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011510
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011511 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011512 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11513 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11514
11515 setFocusedWindow(window);
11516 window->consumeFocusEvent(true);
11517
11518 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11519 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11520 window->assertNoEvents();
11521}
11522
11523TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011524 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011525 auto window = owner.createWindow("Owned window");
11526 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011527 spy->setSpy(true);
11528 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011529 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011530
11531 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11532 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11533 spy->consumeMotionDown();
11534 window->consumeMotionDown();
11535}
11536
11537TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011538 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011539 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011540
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011541 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011542 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011543 randosSpy->setSpy(true);
11544 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011545 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011546
11547 // The event is targeted at owner's window, so injection should succeed, but the spy should
11548 // not receive the event.
11549 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11550 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11551 randosSpy->assertNoEvents();
11552 window->consumeMotionDown();
11553}
11554
11555TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011556 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011557 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011558
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011559 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011560 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011561 randosSpy->setSpy(true);
11562 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011563 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011564
11565 // A user that has injection permission can inject into any window.
11566 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011567 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011568 ADISPLAY_ID_DEFAULT));
11569 randosSpy->consumeMotionDown();
11570 window->consumeMotionDown();
11571
11572 setFocusedWindow(randosSpy);
11573 randosSpy->consumeFocusEvent(true);
11574
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011575 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011576 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11577 window->assertNoEvents();
11578}
11579
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011580TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011581 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011582 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011583
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011584 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011585 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011586 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11587 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011588 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011589
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011590 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011591 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11592 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11593 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011594 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011595}
11596
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011597using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11598
11599TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11600 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11601
11602 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11603 ADISPLAY_ID_DEFAULT);
11604 left->setFrame(Rect(0, 0, 100, 100));
11605 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11606 "Right Window", ADISPLAY_ID_DEFAULT);
11607 right->setFrame(Rect(100, 0, 200, 100));
11608 sp<FakeWindowHandle> spy =
11609 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11610 spy->setFrame(Rect(0, 0, 200, 100));
11611 spy->setTrustedOverlay(true);
11612 spy->setSpy(true);
11613
11614 mDispatcher->onWindowInfosChanged(
11615 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11616
11617 // Hover into the left window.
11618 mDispatcher->notifyMotion(
11619 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11620 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11621 .build());
11622
11623 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11624 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11625
11626 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11627 /*pointerId=*/0));
11628 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11629 /*pointerId=*/0));
11630 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11631 /*pointerId=*/0));
11632
11633 // Hover move to the right window.
11634 mDispatcher->notifyMotion(
11635 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11636 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11637 .build());
11638
11639 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11640 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11641 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11642
11643 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11644 /*pointerId=*/0));
11645 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11646 /*pointerId=*/0));
11647 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11648 /*pointerId=*/0));
11649
11650 // Stop hovering.
11651 mDispatcher->notifyMotion(
11652 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11653 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11654 .build());
11655
11656 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11657 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11658
11659 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11660 /*pointerId=*/0));
11661 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11662 /*pointerId=*/0));
11663 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11664 /*pointerId=*/0));
11665}
11666
11667TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11669
11670 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11671 ADISPLAY_ID_DEFAULT);
11672 left->setFrame(Rect(0, 0, 100, 100));
11673 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11674 "Right Window", ADISPLAY_ID_DEFAULT);
11675 right->setFrame(Rect(100, 0, 200, 100));
11676 sp<FakeWindowHandle> spy =
11677 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11678 spy->setFrame(Rect(0, 0, 200, 100));
11679 spy->setTrustedOverlay(true);
11680 spy->setSpy(true);
11681
11682 mDispatcher->onWindowInfosChanged(
11683 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11684
11685 // First pointer down on left window.
11686 mDispatcher->notifyMotion(
11687 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11688 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11689 .build());
11690
11691 left->consumeMotionDown();
11692 spy->consumeMotionDown();
11693
11694 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11695 /*pointerId=*/0));
11696 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11697 /*pointerId=*/0));
11698 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11699 /*pointerId=*/0));
11700
11701 // Second pointer down on right window.
11702 mDispatcher->notifyMotion(
11703 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11704 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11705 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11706 .build());
11707
11708 left->consumeMotionMove();
11709 right->consumeMotionDown();
11710 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11711
11712 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11713 /*pointerId=*/0));
11714 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11715 /*pointerId=*/0));
11716 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11717 /*pointerId=*/0));
11718 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11719 /*pointerId=*/1));
11720 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11721 /*pointerId=*/1));
11722 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11723 /*pointerId=*/1));
11724
11725 // Second pointer up.
11726 mDispatcher->notifyMotion(
11727 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11728 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11729 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11730 .build());
11731
11732 left->consumeMotionMove();
11733 right->consumeMotionUp();
11734 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11735
11736 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11737 /*pointerId=*/0));
11738 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11739 /*pointerId=*/0));
11740 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11741 /*pointerId=*/0));
11742 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11743 /*pointerId=*/1));
11744 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11745 /*pointerId=*/1));
11746 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11747 /*pointerId=*/1));
11748
11749 // First pointer up.
11750 mDispatcher->notifyMotion(
11751 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11752 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11753 .build());
11754
11755 left->consumeMotionUp();
11756 spy->consumeMotionUp();
11757
11758 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11759 /*pointerId=*/0));
11760 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11761 /*pointerId=*/0));
11762 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11763 /*pointerId=*/0));
11764}
11765
11766TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11768
11769 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11770 ADISPLAY_ID_DEFAULT);
11771 left->setFrame(Rect(0, 0, 100, 100));
11772 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11773 "Right Window", ADISPLAY_ID_DEFAULT);
11774 right->setFrame(Rect(100, 0, 200, 100));
11775
11776 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11777
11778 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11779 /*pointerId=*/0));
11780 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11781 /*pointerId=*/0));
11782
11783 // Hover move into the window.
11784 mDispatcher->notifyMotion(
11785 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11786 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11787 .rawXCursorPosition(50)
11788 .rawYCursorPosition(50)
11789 .deviceId(DEVICE_ID)
11790 .build());
11791
11792 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11793
11794 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11795 /*pointerId=*/0));
11796
11797 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11798 mDispatcher->notifyMotion(
11799 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11800 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11801 .rawXCursorPosition(51)
11802 .rawYCursorPosition(50)
11803 .deviceId(SECOND_DEVICE_ID)
11804 .build());
11805
11806 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11807 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11808
11809 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11810 // a HOVER_EXIT from the first device.
11811 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11812 /*pointerId=*/0));
11813 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11814 SECOND_DEVICE_ID,
11815 /*pointerId=*/0));
11816
11817 // Move the mouse outside the window. Document the current behavior, where the window does not
11818 // receive HOVER_EXIT even though the mouse left the window.
11819 mDispatcher->notifyMotion(
11820 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11821 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11822 .rawXCursorPosition(150)
11823 .rawYCursorPosition(50)
11824 .deviceId(SECOND_DEVICE_ID)
11825 .build());
11826
11827 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11828 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11829 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11830 /*pointerId=*/0));
11831 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11832 SECOND_DEVICE_ID,
11833 /*pointerId=*/0));
11834}
11835
Garfield Tane84e6f92019-08-29 17:28:41 -070011836} // namespace android::inputdispatcher