blob: 72352a365045d7e94bb5de35ade047a6d6085d05 [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,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001096 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001098 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001099 base::Result<std::unique_ptr<InputChannel>> channel =
1100 dispatcher->createInputChannel(name);
1101 token = (*channel)->getConnectionToken();
1102 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001103 }
1104
1105 inputApplicationHandle->updateInfo();
1106 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1107
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001108 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001109 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001110 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001111 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001112 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001113 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001114 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001115 mInfo.globalScaleFactor = 1.0;
1116 mInfo.touchableRegion.clear();
1117 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001118 mInfo.ownerPid = WINDOW_PID;
1119 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001120 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001121 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001122 }
1123
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001124 sp<FakeWindowHandle> clone(int32_t displayId) {
1125 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1126 handle->mInfo = mInfo;
1127 handle->mInfo.displayId = displayId;
1128 handle->mInfo.id = sId++;
1129 handle->mInputReceiver = mInputReceiver;
1130 return handle;
1131 }
1132
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001133 void setTouchable(bool touchable) {
1134 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1135 }
chaviwd1c23182019-12-20 18:44:56 -08001136
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001137 void setFocusable(bool focusable) {
1138 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1139 }
1140
1141 void setVisible(bool visible) {
1142 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1143 }
Vishnu Nair958da932020-08-21 17:12:37 -07001144
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001146 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001147 }
1148
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001149 void setPaused(bool paused) {
1150 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1151 }
1152
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001153 void setPreventSplitting(bool preventSplitting) {
1154 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 }
1156
1157 void setSlippery(bool slippery) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1159 }
1160
1161 void setWatchOutsideTouch(bool watchOutside) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1163 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001164
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001165 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1166
1167 void setInterceptsStylus(bool interceptsStylus) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1169 }
1170
1171 void setDropInput(bool dropInput) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1173 }
1174
1175 void setDropInputIfObscured(bool dropInputIfObscured) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1177 }
1178
1179 void setNoInputChannel(bool noInputChannel) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1181 }
1182
Josep del Riob3981622023-04-18 15:49:45 +00001183 void setDisableUserActivity(bool disableUserActivity) {
1184 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1185 }
1186
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001187 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1188 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1189 shouldGlobalStylusBlockTouch);
1190 }
1191
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001192 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1193
chaviw3277faf2021-05-19 16:45:23 -05001194 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001195
Bernardo Rufino7393d172021-02-26 13:56:11 +00001196 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1197
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001198 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001199 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001200 mInfo.touchableRegion.clear();
1201 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001202
1203 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1204 ui::Transform translate;
1205 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1206 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001207 }
1208
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001209 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1210
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001211 void setIsWallpaper(bool isWallpaper) {
1212 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1213 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001214
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001215 void setDupTouchToWallpaper(bool hasWallpaper) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1217 }
chaviwd1c23182019-12-20 18:44:56 -08001218
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001219 void setTrustedOverlay(bool trustedOverlay) {
1220 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1221 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001222
chaviw9eaa22c2020-07-01 16:21:27 -07001223 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1224 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1225 }
1226
1227 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001228
yunho.shinf4a80b82020-11-16 21:13:57 +09001229 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1230
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001231 const KeyEvent& consumeKey(bool handled = true) {
1232 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1233 if (event.getType() != InputEventType::KEY) {
1234 LOG(FATAL) << "Instead of key event, got " << event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001235 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001236 return static_cast<const KeyEvent&>(event);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001237 }
1238
1239 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001240 const KeyEvent& keyEvent = consumeKey();
1241 ASSERT_THAT(keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001242 }
1243
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001244 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001245 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1246 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001247 }
1248
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001249 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001250 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1251 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001252 }
1253
Svet Ganov5d3bc372020-01-26 23:11:07 -08001254 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001255 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001256 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1257 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001258 }
1259
1260 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001261 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001262 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1263 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001264 }
1265
1266 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001267 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001268 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1269 }
1270
1271 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1272 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001273 consumeMotionEvent(
1274 AllOf(WithMotionAction(ACTION_DOWN),
1275 testing::Conditional(expectedDisplayId.has_value(),
1276 WithDisplayId(*expectedDisplayId), testing::_),
1277 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1278 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001279 }
1280
Svet Ganov5d3bc372020-01-26 23:11:07 -08001281 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001282 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1283 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001284 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001286 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1287 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001288 }
1289
1290 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001291 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001292 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001294 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1295 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001296 }
1297
1298 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001299 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001300 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1301 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001302 }
1303
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001304 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1305 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001306 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1307 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001308 }
1309
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001310 void consumeMotionOutsideWithZeroedCoords() {
1311 consumeMotionEvent(
1312 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001313 }
1314
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001315 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1316 ASSERT_NE(mInputReceiver, nullptr)
1317 << "Cannot consume events from a window with no receiver";
1318 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1319 }
1320
Prabir Pradhan99987712020-11-10 18:43:05 -08001321 void consumeCaptureEvent(bool hasCapture) {
1322 ASSERT_NE(mInputReceiver, nullptr)
1323 << "Cannot consume events from a window with no receiver";
1324 mInputReceiver->consumeCaptureEvent(hasCapture);
1325 }
1326
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001327 const MotionEvent& consumeMotionEvent(
1328 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
1329 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1330 if (event.getType() != InputEventType::MOTION) {
1331 LOG(FATAL) << "Instead of motion event, got " << event;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001332 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001333 const auto& motionEvent = static_cast<const MotionEvent&>(event);
1334 EXPECT_THAT(motionEvent, matcher);
1335 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001336 }
1337
arthurhungb89ccb02020-12-30 16:19:01 +08001338 void consumeDragEvent(bool isExiting, float x, float y) {
1339 mInputReceiver->consumeDragEvent(isExiting, x, y);
1340 }
1341
Antonio Kantekf16f2832021-09-28 04:39:20 +00001342 void consumeTouchModeEvent(bool inTouchMode) {
1343 ASSERT_NE(mInputReceiver, nullptr)
1344 << "Cannot consume events from a window with no receiver";
1345 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1346 }
1347
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001348 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001349 if (mInputReceiver == nullptr) {
1350 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1351 return std::nullopt;
1352 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001353 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001354 }
1355
1356 void finishEvent(uint32_t sequenceNum) {
1357 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1358 mInputReceiver->finishEvent(sequenceNum);
1359 }
1360
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001361 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1362 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1363 mInputReceiver->sendTimeline(inputEventId, timeline);
1364 }
1365
Arthur Hungb92218b2018-08-14 12:00:21 +08001366 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001367 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001368 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001369 return; // Can't receive events if the window does not have input channel
1370 }
1371 ASSERT_NE(nullptr, mInputReceiver)
1372 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001373 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001374 }
1375
chaviwaf87b3e2019-10-01 16:59:28 -07001376 sp<IBinder> getToken() { return mInfo.token; }
1377
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001378 const std::string& getName() { return mName; }
1379
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001380 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001381 mInfo.ownerPid = ownerPid;
1382 mInfo.ownerUid = ownerUid;
1383 }
1384
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001385 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001386
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001387 void destroyReceiver() { mInputReceiver = nullptr; }
1388
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001389 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1390
chaviwd1c23182019-12-20 18:44:56 -08001391private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001392 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001393 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001394 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001395 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001396 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001397
1398 const InputEvent& consume(std::chrono::milliseconds timeout, bool handled = true) {
1399 if (mInputReceiver == nullptr) {
1400 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1401 }
1402 InputEvent* event = mInputReceiver->consume(timeout, handled);
1403 if (event == nullptr) {
1404 LOG(FATAL) << "Consume failed: no event";
1405 }
1406 return *event;
1407 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001408};
1409
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001410std::atomic<int32_t> FakeWindowHandle::sId{1};
1411
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001412class FakeMonitorReceiver {
1413public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001414 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1415 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001416
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001417 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001418
1419 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001420 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1421 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001422 }
1423
1424 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001425 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001426 }
1427
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001428 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001429
1430 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001431 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1432 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001433 }
1434
1435 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001436 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1437 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001438 }
1439
1440 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001441 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1442 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001443 }
1444
1445 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001446 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001447 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1448 WithDisplayId(expectedDisplayId),
1449 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1450 }
1451
1452 void consumeMotionPointerDown(int32_t pointerIdx) {
1453 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1454 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001455 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1456 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001457 }
1458
1459 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001460 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001461 }
1462
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001463 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001464
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001465 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001466
1467private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001468 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001469};
1470
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001472 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001473 int32_t displayId = ADISPLAY_ID_NONE,
1474 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001475 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001476 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001477 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001478 KeyEvent event;
1479 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1480
1481 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001482 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001483 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1484 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001485
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001486 if (!allowKeyRepeat) {
1487 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1488 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001489 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001490 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001491}
1492
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001493static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1494 InputEventInjectionResult result =
1495 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1496 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1497 if (result != InputEventInjectionResult::TIMED_OUT) {
1498 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1499 }
1500}
1501
1502static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001503 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001504 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001505}
1506
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001507// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1508// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1509// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001510static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1511 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001512 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001513 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001514 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001515}
1516
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001517static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001518 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001519 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001520}
1521
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001522static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001523 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001524 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001525 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001526 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001527 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1528 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001529}
1530
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001531static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001532 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1533 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001534 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001535 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1536 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001537 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001538 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001539 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001540 MotionEventBuilder motionBuilder =
1541 MotionEventBuilder(action, source)
1542 .displayId(displayId)
1543 .eventTime(eventTime)
1544 .rawXCursorPosition(cursorPosition.x)
1545 .rawYCursorPosition(cursorPosition.y)
1546 .pointer(
1547 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1548 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1549 motionBuilder.downTime(eventTime);
1550 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001551
1552 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001553 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1554 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001555}
1556
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001557static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1558 int32_t displayId,
1559 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001560 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001561}
1562
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001563static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1564 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001565 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001566 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001567}
1568
Jackal Guof9696682018-10-05 12:23:23 +08001569static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1570 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1571 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001572 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1573 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1574 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001575
1576 return args;
1577}
1578
Josep del Riob3981622023-04-18 15:49:45 +00001579static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1580 int32_t displayId = ADISPLAY_ID_NONE) {
1581 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1582 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001583 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1584 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1585 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001586
1587 return args;
1588}
1589
1590static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1591 int32_t displayId = ADISPLAY_ID_NONE) {
1592 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1593 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001594 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1595 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1596 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001597
1598 return args;
1599}
1600
Prabir Pradhan678438e2023-04-13 19:32:51 +00001601[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1602 int32_t displayId,
1603 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001604 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001605 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1606 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1607 }
1608
chaviwd1c23182019-12-20 18:44:56 -08001609 PointerProperties pointerProperties[pointerCount];
1610 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001611
chaviwd1c23182019-12-20 18:44:56 -08001612 for (size_t i = 0; i < pointerCount; i++) {
1613 pointerProperties[i].clear();
1614 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001615 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001616
chaviwd1c23182019-12-20 18:44:56 -08001617 pointerCoords[i].clear();
1618 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1619 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1620 }
Jackal Guof9696682018-10-05 12:23:23 +08001621
1622 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1623 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001624 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1625 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1626 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001627 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001628 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001629 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001630 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001631
1632 return args;
1633}
1634
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001635static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1636 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1637}
1638
chaviwd1c23182019-12-20 18:44:56 -08001639static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1640 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1641}
1642
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001643static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1644 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001645 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1646 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001647}
1648
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001649} // namespace
1650
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001651/**
1652 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1653 * broken channel.
1654 */
1655TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1657 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001658 sp<FakeWindowHandle>::make(application, mDispatcher,
1659 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001660
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001661 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001662
1663 // Window closes its channel, but the window remains.
1664 window->destroyReceiver();
1665 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1666}
1667
Arthur Hungb92218b2018-08-14 12:00:21 +08001668TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1671 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001673 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001675 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001677
1678 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001679 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001680}
1681
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001682TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001684 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1685 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001688 // Inject a MotionEvent to an unknown display.
1689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001690 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1692
1693 // Window should receive motion event.
1694 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1695}
1696
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001698 * Calling onWindowInfosChanged once should not cause any issues.
1699 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001700 * called twice.
1701 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001702TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1705 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001710 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001711 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713
1714 // Window should receive motion event.
1715 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1716}
1717
1718/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001719 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001720 */
1721TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001723 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1724 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001725 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001730 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001731 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001733
1734 // Window should receive motion event.
1735 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1736}
1737
Arthur Hungb92218b2018-08-14 12:00:21 +08001738// The foreground window should receive the first touch down event.
1739TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001740 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001741 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001742 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001743 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001744 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001745
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001746 mDispatcher->onWindowInfosChanged(
1747 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001749 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001751
1752 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001753 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001754 windowSecond->assertNoEvents();
1755}
1756
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001757/**
1758 * Two windows: A top window, and a wallpaper behind the window.
1759 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1760 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001761 * 1. foregroundWindow <-- dup touch to wallpaper
1762 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001763 */
1764TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1766 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001767 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001768 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001769 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001770 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001771 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001772
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001773 mDispatcher->onWindowInfosChanged(
1774 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001776 injectMotionEvent(*mDispatcher,
1777 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1778 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1779 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1781
1782 // Both foreground window and its wallpaper should receive the touch down
1783 foregroundWindow->consumeMotionDown();
1784 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1785
1786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001787 injectMotionEvent(*mDispatcher,
1788 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1789 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1790 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001791 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1792
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001793 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001794 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1795
1796 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001797 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001798 foregroundWindow->consumeMotionCancel();
1799 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1800 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1801}
1802
1803/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001804 * Two fingers down on the window, and lift off the first finger.
1805 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1806 * contains a single pointer.
1807 */
1808TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1810 sp<FakeWindowHandle> window =
1811 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1812
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001813 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001814 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001815 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1816 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1817 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001818 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001819 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1820 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1821 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1822 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001823 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001824 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1825 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1826 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1827 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001828 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1829 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1830 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1831
1832 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001833 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001834 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1835 window->consumeMotionEvent(
1836 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1837}
1838
1839/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001840 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1841 * with the following differences:
1842 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1843 * clean up the connection.
1844 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1845 * Ensure that there's no crash in the dispatcher.
1846 */
1847TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1849 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001850 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001851 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001852 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001853 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001854 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001855
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001856 mDispatcher->onWindowInfosChanged(
1857 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001859 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001860 {100, 200}))
1861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1862
1863 // Both foreground window and its wallpaper should receive the touch down
1864 foregroundWindow->consumeMotionDown();
1865 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1866
1867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001868 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001869 ADISPLAY_ID_DEFAULT, {110, 200}))
1870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1871
1872 foregroundWindow->consumeMotionMove();
1873 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1874
1875 // Wallpaper closes its channel, but the window remains.
1876 wallpaperWindow->destroyReceiver();
1877 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1878
1879 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1880 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001881 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001882 foregroundWindow->consumeMotionCancel();
1883}
1884
Arthur Hungc539dbb2022-12-08 07:45:36 +00001885class ShouldSplitTouchFixture : public InputDispatcherTest,
1886 public ::testing::WithParamInterface<bool> {};
1887INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1888 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001889/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001890 * A single window that receives touch (on top), and a wallpaper window underneath it.
1891 * The top window gets a multitouch gesture.
1892 * Ensure that wallpaper gets the same gesture.
1893 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001894TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001895 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001896 sp<FakeWindowHandle> foregroundWindow =
1897 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1898 foregroundWindow->setDupTouchToWallpaper(true);
1899 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900
1901 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001902 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001903 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001905 mDispatcher->onWindowInfosChanged(
1906 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907
1908 // Touch down on top window
1909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001910 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911 {100, 100}))
1912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1913
1914 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001915 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001916 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1917
1918 // Second finger down on the top window
1919 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001920 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001921 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001922 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1923 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001924 .build();
1925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001926 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001927 InputEventInjectionSync::WAIT_FOR_RESULT))
1928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1929
Harry Cutts33476232023-01-30 19:57:29 +00001930 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1931 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001932 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001933
1934 const MotionEvent secondFingerUpEvent =
1935 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1936 .displayId(ADISPLAY_ID_DEFAULT)
1937 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001938 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1939 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001940 .build();
1941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001942 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001943 InputEventInjectionSync::WAIT_FOR_RESULT))
1944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1945 foregroundWindow->consumeMotionPointerUp(0);
1946 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1947
1948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001949 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001950 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1951 AINPUT_SOURCE_TOUCHSCREEN)
1952 .displayId(ADISPLAY_ID_DEFAULT)
1953 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001954 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001955 .x(100)
1956 .y(100))
1957 .build(),
1958 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1960 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1961 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001962}
1963
1964/**
1965 * Two windows: a window on the left and window on the right.
1966 * A third window, wallpaper, is behind both windows, and spans both top windows.
1967 * The first touch down goes to the left window. A second pointer touches down on the right window.
1968 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1969 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1970 * ACTION_POINTER_DOWN(1).
1971 */
1972TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1974 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001975 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001976 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001977 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978
1979 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001980 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001981 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001982 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001983
1984 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001985 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001986 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001987 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001989 mDispatcher->onWindowInfosChanged(
1990 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1991 {},
1992 0,
1993 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001994
1995 // Touch down on left window
1996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001997 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 {100, 100}))
1999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2000
2001 // Both foreground window and its wallpaper should receive the touch down
2002 leftWindow->consumeMotionDown();
2003 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2004
2005 // Second finger down on the right window
2006 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002007 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002008 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002009 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2010 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002011 .build();
2012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002013 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002014 InputEventInjectionSync::WAIT_FOR_RESULT))
2015 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2016
2017 leftWindow->consumeMotionMove();
2018 // Since the touch is split, right window gets ACTION_DOWN
2019 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002020 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 expectedWallpaperFlags);
2022
2023 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002024 mDispatcher->onWindowInfosChanged(
2025 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026 leftWindow->consumeMotionCancel();
2027 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2028 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2029
2030 // The pointer that's still down on the right window moves, and goes to the right window only.
2031 // As far as the dispatcher's concerned though, both pointers are still present.
2032 const MotionEvent secondFingerMoveEvent =
2033 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2034 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002035 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2036 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002037 .build();
2038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002039 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040 InputEventInjectionSync::WAIT_FOR_RESULT));
2041 rightWindow->consumeMotionMove();
2042
2043 leftWindow->assertNoEvents();
2044 rightWindow->assertNoEvents();
2045 wallpaperWindow->assertNoEvents();
2046}
2047
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048/**
2049 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2050 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2051 * The right window should receive ACTION_DOWN.
2052 */
2053TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002054 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055 sp<FakeWindowHandle> leftWindow =
2056 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2057 leftWindow->setFrame(Rect(0, 0, 200, 200));
2058 leftWindow->setDupTouchToWallpaper(true);
2059 leftWindow->setSlippery(true);
2060
2061 sp<FakeWindowHandle> rightWindow =
2062 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2063 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002064
2065 sp<FakeWindowHandle> wallpaperWindow =
2066 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2067 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002068
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002069 mDispatcher->onWindowInfosChanged(
2070 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2071 {},
2072 0,
2073 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002074
Arthur Hungc539dbb2022-12-08 07:45:36 +00002075 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002077 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002078 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002079 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002080
2081 // Both foreground window and its wallpaper should receive the touch down
2082 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002083 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2084
Arthur Hungc539dbb2022-12-08 07:45:36 +00002085 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002087 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002088 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2090
Arthur Hungc539dbb2022-12-08 07:45:36 +00002091 leftWindow->consumeMotionCancel();
2092 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2093 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002094}
2095
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002096/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002097 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2098 * interactive, it might stop sending this flag.
2099 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2100 * to have a consistent input stream.
2101 *
2102 * Test procedure:
2103 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2104 * DOWN (new gesture).
2105 *
2106 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2107 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2108 *
2109 * We technically just need a single window here, but we are using two windows (spy on top and a
2110 * regular window below) to emulate the actual situation where it happens on the device.
2111 */
2112TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2114 sp<FakeWindowHandle> spyWindow =
2115 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2116 spyWindow->setFrame(Rect(0, 0, 200, 200));
2117 spyWindow->setTrustedOverlay(true);
2118 spyWindow->setSpy(true);
2119
2120 sp<FakeWindowHandle> window =
2121 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2122 window->setFrame(Rect(0, 0, 200, 200));
2123
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002124 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002125 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126
2127 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002128 mDispatcher->notifyMotion(
2129 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2130 .deviceId(touchDeviceId)
2131 .policyFlags(DEFAULT_POLICY_FLAGS)
2132 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2133 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002134
Prabir Pradhan678438e2023-04-13 19:32:51 +00002135 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2136 .deviceId(touchDeviceId)
2137 .policyFlags(DEFAULT_POLICY_FLAGS)
2138 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2139 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2140 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002141 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2142 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2143 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2144 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2145
2146 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002147 mDispatcher->notifyMotion(
2148 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2149 .deviceId(touchDeviceId)
2150 .policyFlags(0)
2151 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2152 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2153 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002154 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2155 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2156
2157 // We don't need to reset the device to reproduce the issue, but the reset event typically
2158 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002159 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002160
2161 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002162 mDispatcher->notifyMotion(
2163 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2164 .deviceId(touchDeviceId)
2165 .policyFlags(DEFAULT_POLICY_FLAGS)
2166 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2167 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002168 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2169 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2170
2171 // No more events
2172 spyWindow->assertNoEvents();
2173 window->assertNoEvents();
2174}
2175
2176/**
Linnan Li907ae732023-09-05 17:14:21 +08002177 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2178 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2179 * interactive, it might stop sending this flag.
2180 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2181 * the consistency of the hover event in this case.
2182 *
2183 * Test procedure:
2184 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2185 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2186 *
2187 * We expect to receive two full streams of hover events.
2188 */
2189TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2191
2192 sp<FakeWindowHandle> window =
2193 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2194 window->setFrame(Rect(0, 0, 300, 300));
2195
2196 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2197
2198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2199 .policyFlags(DEFAULT_POLICY_FLAGS)
2200 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2201 .build());
2202 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2203
2204 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2205 .policyFlags(DEFAULT_POLICY_FLAGS)
2206 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2207 .build());
2208 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2209
2210 // Send hover exit without the default policy flags.
2211 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2212 .policyFlags(0)
2213 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2214 .build());
2215
2216 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2217
2218 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2219 // right event.
2220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2221 .policyFlags(DEFAULT_POLICY_FLAGS)
2222 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2223 .build());
2224 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2225
2226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2227 .policyFlags(DEFAULT_POLICY_FLAGS)
2228 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2229 .build());
2230 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2231
2232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2233 .policyFlags(DEFAULT_POLICY_FLAGS)
2234 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2235 .build());
2236 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2237}
2238
2239/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002240 * Two windows: a window on the left and a window on the right.
2241 * Mouse is hovered from the right window into the left window.
2242 * Next, we tap on the left window, where the cursor was last seen.
2243 * The second tap is done onto the right window.
2244 * The mouse and tap are from two different devices.
2245 * We technically don't need to set the downtime / eventtime for these events, but setting these
2246 * explicitly helps during debugging.
2247 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2248 * In the buggy implementation, a tap on the right window would cause a crash.
2249 */
2250TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2251 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2252 sp<FakeWindowHandle> leftWindow =
2253 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2254 leftWindow->setFrame(Rect(0, 0, 200, 200));
2255
2256 sp<FakeWindowHandle> rightWindow =
2257 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2258 rightWindow->setFrame(Rect(200, 0, 400, 200));
2259
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002260 mDispatcher->onWindowInfosChanged(
2261 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002262 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2263 // stale.
2264 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2265 const int32_t mouseDeviceId = 6;
2266 const int32_t touchDeviceId = 4;
2267 // Move the cursor from right
2268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002269 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002270 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2271 AINPUT_SOURCE_MOUSE)
2272 .deviceId(mouseDeviceId)
2273 .downTime(baseTime + 10)
2274 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002275 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002276 .build()));
2277 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2278
2279 // .. to the left window
2280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002281 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002282 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2283 AINPUT_SOURCE_MOUSE)
2284 .deviceId(mouseDeviceId)
2285 .downTime(baseTime + 10)
2286 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002287 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002288 .build()));
2289 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2290 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2291 // Now tap the left window
2292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002293 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002294 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2295 AINPUT_SOURCE_TOUCHSCREEN)
2296 .deviceId(touchDeviceId)
2297 .downTime(baseTime + 40)
2298 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002299 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002300 .build()));
2301 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2302 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2303
2304 // release tap
2305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002306 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002307 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2308 AINPUT_SOURCE_TOUCHSCREEN)
2309 .deviceId(touchDeviceId)
2310 .downTime(baseTime + 40)
2311 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002312 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002313 .build()));
2314 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2315
2316 // Tap the window on the right
2317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002319 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2320 AINPUT_SOURCE_TOUCHSCREEN)
2321 .deviceId(touchDeviceId)
2322 .downTime(baseTime + 60)
2323 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002324 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002325 .build()));
2326 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2327
2328 // release tap
2329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002330 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002331 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2332 AINPUT_SOURCE_TOUCHSCREEN)
2333 .deviceId(touchDeviceId)
2334 .downTime(baseTime + 60)
2335 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002336 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002337 .build()));
2338 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2339
2340 // No more events
2341 leftWindow->assertNoEvents();
2342 rightWindow->assertNoEvents();
2343}
2344
2345/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002346 * Start hovering in a window. While this hover is still active, make another window appear on top.
2347 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2348 * While the top window is present, the hovering is stopped.
2349 * Later, hovering gets resumed again.
2350 * Ensure that new hover gesture is handled correctly.
2351 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2352 * to the window that's currently being hovered over.
2353 */
2354TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2355 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2356 sp<FakeWindowHandle> window =
2357 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2358 window->setFrame(Rect(0, 0, 200, 200));
2359
2360 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002361 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002362
2363 // Start hovering in the window
2364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2365 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2366 .build());
2367 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2368
2369 // Now, an obscuring window appears!
2370 sp<FakeWindowHandle> obscuringWindow =
2371 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2372 ADISPLAY_ID_DEFAULT,
2373 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2374 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2375 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2376 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2377 obscuringWindow->setNoInputChannel(true);
2378 obscuringWindow->setFocusable(false);
2379 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002380 mDispatcher->onWindowInfosChanged(
2381 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002382
2383 // While this new obscuring window is present, the hovering is stopped
2384 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2385 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2386 .build());
2387 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2388
2389 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002390 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002391
2392 // And a new hover gesture starts.
2393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2394 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2395 .build());
2396 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2397}
2398
2399/**
2400 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2401 * the obscuring window.
2402 */
2403TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2405 sp<FakeWindowHandle> window =
2406 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2407 window->setFrame(Rect(0, 0, 200, 200));
2408
2409 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002410 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002411
2412 // Start hovering in the window
2413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2414 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2415 .build());
2416 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2417
2418 // Now, an obscuring window appears!
2419 sp<FakeWindowHandle> obscuringWindow =
2420 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2421 ADISPLAY_ID_DEFAULT,
2422 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2423 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2424 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2425 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2426 obscuringWindow->setNoInputChannel(true);
2427 obscuringWindow->setFocusable(false);
2428 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002429 mDispatcher->onWindowInfosChanged(
2430 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002431
2432 // While this new obscuring window is present, the hovering continues. The event can't go to the
2433 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2434 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2435 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2436 .build());
2437 obscuringWindow->assertNoEvents();
2438 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2439
2440 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002441 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002442
2443 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2444 // so it should generate a HOVER_ENTER
2445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2446 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2447 .build());
2448 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2449
2450 // Now the MOVE should be getting dispatched normally
2451 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2452 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2453 .build());
2454 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2455}
2456
2457/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002458 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2459 * events are delivered to the window.
2460 */
2461TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2463 sp<FakeWindowHandle> window =
2464 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2465 window->setFrame(Rect(0, 0, 200, 200));
2466 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2467
2468 // Start hovering in the window
2469 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2470 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2471 .build());
2472 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2473
2474 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2475 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2476 .build());
2477 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2478
2479 // Scroll with the mouse
2480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2481 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2482 .build());
2483 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2484}
2485
2486using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2487
2488/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002489 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2490 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002491 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002492TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2494 sp<FakeWindowHandle> window =
2495 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2496 window->setFrame(Rect(0, 0, 200, 200));
2497
2498 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2499
2500 constexpr int32_t touchDeviceId = 4;
2501 constexpr int32_t stylusDeviceId = 2;
2502
2503 // Stylus down
2504 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2505 .deviceId(stylusDeviceId)
2506 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2507 .build());
2508 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2509
2510 // Touch down
2511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2512 .deviceId(touchDeviceId)
2513 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2514 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002515
2516 // Touch move
2517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2518 .deviceId(touchDeviceId)
2519 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2520 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002521 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002522
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002523 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2525 .deviceId(stylusDeviceId)
2526 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2527 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002528 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2529 WithCoords(101, 111)));
2530
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002531 window->assertNoEvents();
2532}
2533
2534/**
2535 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002536 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002537 * Similar test as above, but with added SPY window.
2538 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002539TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2541 sp<FakeWindowHandle> window =
2542 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2543 sp<FakeWindowHandle> spyWindow =
2544 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2545 spyWindow->setFrame(Rect(0, 0, 200, 200));
2546 spyWindow->setTrustedOverlay(true);
2547 spyWindow->setSpy(true);
2548 window->setFrame(Rect(0, 0, 200, 200));
2549
2550 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2551
2552 constexpr int32_t touchDeviceId = 4;
2553 constexpr int32_t stylusDeviceId = 2;
2554
2555 // Stylus down
2556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2557 .deviceId(stylusDeviceId)
2558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2559 .build());
2560 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2561 spyWindow->consumeMotionEvent(
2562 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2563
2564 // Touch down
2565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2566 .deviceId(touchDeviceId)
2567 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2568 .build());
2569
2570 // Touch move
2571 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2572 .deviceId(touchDeviceId)
2573 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2574 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002575
2576 // Touch is ignored because stylus is already down
2577
2578 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2580 .deviceId(stylusDeviceId)
2581 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2582 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002583 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2584 WithCoords(101, 111)));
2585 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2586 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002587
2588 window->assertNoEvents();
2589 spyWindow->assertNoEvents();
2590}
2591
2592/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002593 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002594 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002595 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002596TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2598 sp<FakeWindowHandle> window =
2599 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2600 window->setFrame(Rect(0, 0, 200, 200));
2601
2602 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2603
2604 constexpr int32_t touchDeviceId = 4;
2605 constexpr int32_t stylusDeviceId = 2;
2606
2607 // Stylus down on the window
2608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2609 .deviceId(stylusDeviceId)
2610 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2611 .build());
2612 window->consumeMotionEvent(
2613 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2614
2615 // Touch down on window
2616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2617 .deviceId(touchDeviceId)
2618 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2619 .build());
2620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2621 .deviceId(touchDeviceId)
2622 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2623 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002624
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002625 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002626
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002627 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002628 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2629 .deviceId(stylusDeviceId)
2630 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2631 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002632 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2633 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002634
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002635 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2637 .deviceId(touchDeviceId)
2638 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2639 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002640 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002641}
2642
2643/**
2644 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002645 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002646 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002647TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2649 sp<FakeWindowHandle> window =
2650 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2651 window->setFrame(Rect(0, 0, 200, 200));
2652
2653 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2654
2655 constexpr int32_t touchDeviceId = 4;
2656 constexpr int32_t stylusDeviceId = 2;
2657
2658 // Touch down on window
2659 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2660 .deviceId(touchDeviceId)
2661 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2662 .build());
2663 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2664 .deviceId(touchDeviceId)
2665 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2666 .build());
2667 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2668 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2669
2670 // Stylus hover on the window
2671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2672 .deviceId(stylusDeviceId)
2673 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2674 .build());
2675 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2676 .deviceId(stylusDeviceId)
2677 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2678 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002679 // Stylus hover movement causes touch to be canceled
2680 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2681 WithCoords(141, 146)));
2682 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2683 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2684 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2685 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002686
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002687 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2689 .deviceId(touchDeviceId)
2690 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2691 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002692
2693 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002694}
2695
2696/**
2697 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2698 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2699 * become active.
2700 */
2701TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2703 sp<FakeWindowHandle> window =
2704 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2705 window->setFrame(Rect(0, 0, 200, 200));
2706
2707 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2708
2709 constexpr int32_t stylusDeviceId1 = 3;
2710 constexpr int32_t stylusDeviceId2 = 5;
2711
2712 // Touch down on window
2713 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2714 .deviceId(stylusDeviceId1)
2715 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2716 .build());
2717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2718 .deviceId(stylusDeviceId1)
2719 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2720 .build());
2721 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2722 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2723
2724 // Second stylus down
2725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2726 .deviceId(stylusDeviceId2)
2727 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2728 .build());
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2730 .deviceId(stylusDeviceId2)
2731 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2732 .build());
2733
2734 // First stylus is canceled, second one takes over.
2735 window->consumeMotionEvent(
2736 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2737 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2738 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2739
2740 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2741 .deviceId(stylusDeviceId1)
2742 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2743 .build());
2744 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002745 window->assertNoEvents();
2746}
2747
2748/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002749 * One window. Touch down on the window. Then, stylus down on the window from another device.
2750 * Ensure that is canceled, because stylus down should be preferred over touch.
2751 */
2752TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2754 sp<FakeWindowHandle> window =
2755 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2756 window->setFrame(Rect(0, 0, 200, 200));
2757
2758 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2759
2760 constexpr int32_t touchDeviceId = 4;
2761 constexpr int32_t stylusDeviceId = 2;
2762
2763 // Touch down on window
2764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2765 .deviceId(touchDeviceId)
2766 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2767 .build());
2768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2769 .deviceId(touchDeviceId)
2770 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2771 .build());
2772 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2773 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2774
2775 // Stylus down on the window
2776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2777 .deviceId(stylusDeviceId)
2778 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2779 .build());
2780 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2782
2783 // Subsequent stylus movements are delivered correctly
2784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2785 .deviceId(stylusDeviceId)
2786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2787 .build());
2788 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2789 WithCoords(101, 111)));
2790}
2791
2792/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002793 * Two windows: a window on the left and a window on the right.
2794 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2795 * down. Then, on the left window, also place second touch pointer down.
2796 * This test tries to reproduce a crash.
2797 * In the buggy implementation, second pointer down on the left window would cause a crash.
2798 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002799TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002800 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2801 sp<FakeWindowHandle> leftWindow =
2802 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2803 leftWindow->setFrame(Rect(0, 0, 200, 200));
2804
2805 sp<FakeWindowHandle> rightWindow =
2806 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2807 rightWindow->setFrame(Rect(200, 0, 400, 200));
2808
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002809 mDispatcher->onWindowInfosChanged(
2810 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002811
2812 const int32_t touchDeviceId = 4;
2813 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002814
2815 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2817 .deviceId(mouseDeviceId)
2818 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2819 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002820 leftWindow->consumeMotionEvent(
2821 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2822
2823 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2825 .deviceId(mouseDeviceId)
2826 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2828 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002829
2830 leftWindow->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2832 leftWindow->consumeMotionEvent(
2833 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2834
Prabir Pradhan678438e2023-04-13 19:32:51 +00002835 mDispatcher->notifyMotion(
2836 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2837 .deviceId(mouseDeviceId)
2838 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2839 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2840 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2841 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002842 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2843
2844 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2846 .deviceId(touchDeviceId)
2847 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2848 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002849 leftWindow->assertNoEvents();
2850
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002851 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2852
2853 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002854 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2855 .deviceId(touchDeviceId)
2856 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2857 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2858 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002859 // Since this is now a new splittable pointer going down on the left window, and it's coming
2860 // from a different device, the current gesture in the left window (pointer down) should first
2861 // be canceled.
2862 leftWindow->consumeMotionEvent(
2863 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002864 leftWindow->consumeMotionEvent(
2865 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2866 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2867 // current implementation.
2868 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2869 rightWindow->consumeMotionEvent(
2870 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2871
2872 leftWindow->assertNoEvents();
2873 rightWindow->assertNoEvents();
2874}
2875
2876/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002877 * Two windows: a window on the left and a window on the right.
2878 * Mouse is hovered on the left window and stylus is hovered on the right window.
2879 */
2880TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2882 sp<FakeWindowHandle> leftWindow =
2883 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2884 leftWindow->setFrame(Rect(0, 0, 200, 200));
2885
2886 sp<FakeWindowHandle> rightWindow =
2887 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2888 rightWindow->setFrame(Rect(200, 0, 400, 200));
2889
2890 mDispatcher->onWindowInfosChanged(
2891 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2892
2893 const int32_t stylusDeviceId = 3;
2894 const int32_t mouseDeviceId = 6;
2895
2896 // Start hovering over the left window
2897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2898 .deviceId(mouseDeviceId)
2899 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2900 .build());
2901 leftWindow->consumeMotionEvent(
2902 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2903
2904 // Stylus hovered on right window
2905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2906 .deviceId(stylusDeviceId)
2907 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2908 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002909 rightWindow->consumeMotionEvent(
2910 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2911
2912 // Subsequent HOVER_MOVE events are dispatched correctly.
2913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2914 .deviceId(mouseDeviceId)
2915 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2916 .build());
2917 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002918 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002919
2920 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2921 .deviceId(stylusDeviceId)
2922 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2923 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002924 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002925 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002926
2927 leftWindow->assertNoEvents();
2928 rightWindow->assertNoEvents();
2929}
2930
2931/**
2932 * Three windows: a window on the left and a window on the right.
2933 * And a spy window that's positioned above all of them.
2934 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2935 * Check the stream that's received by the spy.
2936 */
2937TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2939
2940 sp<FakeWindowHandle> spyWindow =
2941 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2942 spyWindow->setFrame(Rect(0, 0, 400, 400));
2943 spyWindow->setTrustedOverlay(true);
2944 spyWindow->setSpy(true);
2945
2946 sp<FakeWindowHandle> leftWindow =
2947 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2948 leftWindow->setFrame(Rect(0, 0, 200, 200));
2949
2950 sp<FakeWindowHandle> rightWindow =
2951 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2952
2953 rightWindow->setFrame(Rect(200, 0, 400, 200));
2954
2955 mDispatcher->onWindowInfosChanged(
2956 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2957
2958 const int32_t stylusDeviceId = 1;
2959 const int32_t touchDeviceId = 2;
2960
2961 // Stylus down on the left window
2962 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2963 .deviceId(stylusDeviceId)
2964 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2965 .build());
2966 leftWindow->consumeMotionEvent(
2967 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2968 spyWindow->consumeMotionEvent(
2969 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2970
2971 // Touch down on the right window
2972 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2973 .deviceId(touchDeviceId)
2974 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2975 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002976 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002977 rightWindow->consumeMotionEvent(
2978 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002979
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002980 // Spy window does not receive touch events, because stylus events take precedence, and it
2981 // already has an active stylus gesture.
2982
2983 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2985 .deviceId(stylusDeviceId)
2986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2987 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002988 leftWindow->consumeMotionEvent(
2989 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2990 spyWindow->consumeMotionEvent(
2991 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002992
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002993 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002994 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2995 .deviceId(touchDeviceId)
2996 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2997 .build());
2998 rightWindow->consumeMotionEvent(
2999 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003000
3001 spyWindow->assertNoEvents();
3002 leftWindow->assertNoEvents();
3003 rightWindow->assertNoEvents();
3004}
3005
3006/**
3007 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3008 * both.
3009 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003010 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003011 * At the same time, left and right should be getting independent streams of hovering and touch,
3012 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003013 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003014TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3016
3017 sp<FakeWindowHandle> spyWindow =
3018 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3019 spyWindow->setFrame(Rect(0, 0, 400, 400));
3020 spyWindow->setTrustedOverlay(true);
3021 spyWindow->setSpy(true);
3022
3023 sp<FakeWindowHandle> leftWindow =
3024 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3025 leftWindow->setFrame(Rect(0, 0, 200, 200));
3026
3027 sp<FakeWindowHandle> rightWindow =
3028 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3029 rightWindow->setFrame(Rect(200, 0, 400, 200));
3030
3031 mDispatcher->onWindowInfosChanged(
3032 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3033
3034 const int32_t stylusDeviceId = 1;
3035 const int32_t touchDeviceId = 2;
3036
3037 // Stylus hover on the left window
3038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3039 .deviceId(stylusDeviceId)
3040 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3041 .build());
3042 leftWindow->consumeMotionEvent(
3043 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3044 spyWindow->consumeMotionEvent(
3045 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3046
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003047 // Touch down on the right window. Spy doesn't receive this touch because it already has
3048 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003049 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3050 .deviceId(touchDeviceId)
3051 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3052 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003053 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003054 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003055 rightWindow->consumeMotionEvent(
3056 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3057
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003058 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003059 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3060 .deviceId(stylusDeviceId)
3061 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3062 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003063 leftWindow->consumeMotionEvent(
3064 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003065 spyWindow->consumeMotionEvent(
3066 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003067
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003068 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3070 .deviceId(touchDeviceId)
3071 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3072 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003073 rightWindow->consumeMotionEvent(
3074 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3075
3076 spyWindow->assertNoEvents();
3077 leftWindow->assertNoEvents();
3078 rightWindow->assertNoEvents();
3079}
3080
3081/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003082 * On a single window, use two different devices: mouse and touch.
3083 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3084 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3085 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3086 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3087 * represent a new gesture.
3088 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003089TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003090 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3091 sp<FakeWindowHandle> window =
3092 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3093 window->setFrame(Rect(0, 0, 400, 400));
3094
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003095 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003096
3097 const int32_t touchDeviceId = 4;
3098 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003099
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003100 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3102 .deviceId(touchDeviceId)
3103 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3104 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003105 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003106 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3107 .deviceId(touchDeviceId)
3108 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3109 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3110 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003111 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3113 .deviceId(touchDeviceId)
3114 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3115 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3116 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003117 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3118 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3119 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3120
3121 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3123 .deviceId(mouseDeviceId)
3124 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3125 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3126 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127
3128 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003129 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003130 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3131
Prabir Pradhan678438e2023-04-13 19:32:51 +00003132 mDispatcher->notifyMotion(
3133 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3134 .deviceId(mouseDeviceId)
3135 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3136 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3137 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3138 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3140
3141 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003142 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3143 .deviceId(touchDeviceId)
3144 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3145 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3146 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003147 // Since we already canceled this touch gesture, it will be ignored until a completely new
3148 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3149 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3150 // However, mouse movements should continue to work.
3151 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3152 .deviceId(mouseDeviceId)
3153 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3154 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3155 .build());
3156 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3157
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003158 window->assertNoEvents();
3159}
3160
3161/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003162 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3163 * the injected event.
3164 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003165TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003166 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3167 sp<FakeWindowHandle> window =
3168 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3169 window->setFrame(Rect(0, 0, 400, 400));
3170
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003171 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003172
3173 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003174 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3175 // completion.
3176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003177 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003178 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3179 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003180 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003181 .build()));
3182 window->consumeMotionEvent(
3183 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3184
3185 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3186 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003187 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3188 .deviceId(touchDeviceId)
3189 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3190 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003191
3192 window->consumeMotionEvent(
3193 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3194 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3195}
3196
3197/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003198 * This test is similar to the test above, but the sequence of injected events is different.
3199 *
3200 * Two windows: a window on the left and a window on the right.
3201 * Mouse is hovered over the left window.
3202 * Next, we tap on the left window, where the cursor was last seen.
3203 *
3204 * After that, we inject one finger down onto the right window, and then a second finger down onto
3205 * the left window.
3206 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3207 * window (first), and then another on the left window (second).
3208 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3209 * In the buggy implementation, second finger down on the left window would cause a crash.
3210 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003211TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3213 sp<FakeWindowHandle> leftWindow =
3214 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3215 leftWindow->setFrame(Rect(0, 0, 200, 200));
3216
3217 sp<FakeWindowHandle> rightWindow =
3218 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3219 rightWindow->setFrame(Rect(200, 0, 400, 200));
3220
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003221 mDispatcher->onWindowInfosChanged(
3222 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003223
3224 const int32_t mouseDeviceId = 6;
3225 const int32_t touchDeviceId = 4;
3226 // Hover over the left window. Keep the cursor there.
3227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003228 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003229 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3230 AINPUT_SOURCE_MOUSE)
3231 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003232 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003233 .build()));
3234 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3235
3236 // Tap on left window
3237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003238 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003239 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3240 AINPUT_SOURCE_TOUCHSCREEN)
3241 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003242 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003243 .build()));
3244
3245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003246 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003247 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3248 AINPUT_SOURCE_TOUCHSCREEN)
3249 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003250 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003251 .build()));
3252 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3253 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3254 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3255
3256 // First finger down on right window
3257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003258 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003259 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3260 AINPUT_SOURCE_TOUCHSCREEN)
3261 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003262 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003263 .build()));
3264 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3265
3266 // Second finger down on the left window
3267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003268 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003269 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003271 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3272 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003273 .build()));
3274 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3275 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3276
3277 // No more events
3278 leftWindow->assertNoEvents();
3279 rightWindow->assertNoEvents();
3280}
3281
3282/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003283 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3284 * While the touch is down, new hover events from the stylus device should be ignored. After the
3285 * touch is gone, stylus hovering should start working again.
3286 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003287TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3289 sp<FakeWindowHandle> window =
3290 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3291 window->setFrame(Rect(0, 0, 200, 200));
3292
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003293 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003294
3295 const int32_t stylusDeviceId = 5;
3296 const int32_t touchDeviceId = 4;
3297 // Start hovering with stylus
3298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003299 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003300 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003301 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003302 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003303 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003304 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003305
3306 // Finger down on the window
3307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003309 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003310 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003311 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003313 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003314
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003315 // Continue hovering with stylus.
3316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003317 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003318 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3319 AINPUT_SOURCE_STYLUS)
3320 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003321 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003322 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003323 // Hovers continue to work
3324 window->consumeMotionEvent(
3325 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003326
3327 // Lift up the finger
3328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003329 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003330 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3331 AINPUT_SOURCE_TOUCHSCREEN)
3332 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003333 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003334 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003338 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3339 AINPUT_SOURCE_STYLUS)
3340 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003341 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003342 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003343 window->consumeMotionEvent(
3344 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003345 window->assertNoEvents();
3346}
3347
3348/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003349 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3350 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3351 *
3352 * Two windows: one on the left and one on the right.
3353 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3354 * Stylus down on the left window, and then touch down on the right window.
3355 * Check that the right window doesn't get touches while the stylus is down on the left window.
3356 */
3357TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3359 sp<FakeWindowHandle> leftWindow =
3360 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3361 ADISPLAY_ID_DEFAULT);
3362 leftWindow->setFrame(Rect(0, 0, 100, 100));
3363
3364 sp<FakeWindowHandle> sbtRightWindow =
3365 sp<FakeWindowHandle>::make(application, mDispatcher,
3366 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3367 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3368 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3369
3370 mDispatcher->onWindowInfosChanged(
3371 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3372
3373 const int32_t stylusDeviceId = 5;
3374 const int32_t touchDeviceId = 4;
3375
3376 // Stylus down in the left window
3377 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3378 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3379 .deviceId(stylusDeviceId)
3380 .build());
3381 leftWindow->consumeMotionEvent(
3382 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3383
3384 // Finger tap on the right window
3385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3386 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3387 .deviceId(touchDeviceId)
3388 .build());
3389 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3390 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3391 .deviceId(touchDeviceId)
3392 .build());
3393
3394 // The touch should be blocked, because stylus is down somewhere else on screen!
3395 sbtRightWindow->assertNoEvents();
3396
3397 // Continue stylus motion, and ensure it's not impacted.
3398 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3399 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3400 .deviceId(stylusDeviceId)
3401 .build());
3402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3403 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3404 .deviceId(stylusDeviceId)
3405 .build());
3406 leftWindow->consumeMotionEvent(
3407 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3408 leftWindow->consumeMotionEvent(
3409 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3410
3411 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3413 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3414 .deviceId(touchDeviceId)
3415 .build());
3416 sbtRightWindow->consumeMotionEvent(
3417 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3418}
3419
3420/**
3421 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3422 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3423 *
3424 * Two windows: one on the left and one on the right.
3425 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3426 * Stylus hover on the left window, and then touch down on the right window.
3427 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3428 */
3429TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3430 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3431 sp<FakeWindowHandle> leftWindow =
3432 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3433 ADISPLAY_ID_DEFAULT);
3434 leftWindow->setFrame(Rect(0, 0, 100, 100));
3435
3436 sp<FakeWindowHandle> sbtRightWindow =
3437 sp<FakeWindowHandle>::make(application, mDispatcher,
3438 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3439 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3440 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3441
3442 mDispatcher->onWindowInfosChanged(
3443 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3444
3445 const int32_t stylusDeviceId = 5;
3446 const int32_t touchDeviceId = 4;
3447
3448 // Stylus hover in the left window
3449 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3450 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3451 .deviceId(stylusDeviceId)
3452 .build());
3453 leftWindow->consumeMotionEvent(
3454 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3455
3456 // Finger tap on the right window
3457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3458 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3459 .deviceId(touchDeviceId)
3460 .build());
3461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3462 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3463 .deviceId(touchDeviceId)
3464 .build());
3465
3466 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3467 sbtRightWindow->assertNoEvents();
3468
3469 // Continue stylus motion, and ensure it's not impacted.
3470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3471 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3472 .deviceId(stylusDeviceId)
3473 .build());
3474 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3475 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3476 .deviceId(stylusDeviceId)
3477 .build());
3478 leftWindow->consumeMotionEvent(
3479 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3480 leftWindow->consumeMotionEvent(
3481 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3482
3483 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3485 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3486 .deviceId(touchDeviceId)
3487 .build());
3488 sbtRightWindow->consumeMotionEvent(
3489 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3490}
3491
3492/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003493 * A spy window above a window with no input channel.
3494 * Start hovering with a stylus device, and then tap with it.
3495 * Ensure spy window receives the entire sequence.
3496 */
3497TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3498 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3499 sp<FakeWindowHandle> spyWindow =
3500 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3501 spyWindow->setFrame(Rect(0, 0, 200, 200));
3502 spyWindow->setTrustedOverlay(true);
3503 spyWindow->setSpy(true);
3504 sp<FakeWindowHandle> window =
3505 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3506 window->setNoInputChannel(true);
3507 window->setFrame(Rect(0, 0, 200, 200));
3508
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003509 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003510
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003511 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3513 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3514 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003515 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3516 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3518 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3519 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003520 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3521
3522 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3524 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3525 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003526 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3527
3528 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3530 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3531 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003532 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3533
3534 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3536 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3537 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003538 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3539 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3542 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003543 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3544
3545 // No more events
3546 spyWindow->assertNoEvents();
3547 window->assertNoEvents();
3548}
3549
3550/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003551 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3552 * rejected. But since we already have an ongoing gesture, this event should be processed.
3553 * This prevents inconsistent events being handled inside the dispatcher.
3554 */
3555TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3557
3558 sp<FakeWindowHandle> window =
3559 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3560 window->setFrame(Rect(0, 0, 200, 200));
3561
3562 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3563
3564 // Start hovering with stylus
3565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3566 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3567 .build());
3568 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3569
3570 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3572 .build();
3573 // Make this 'hoverExit' event stale
3574 mFakePolicy->setStaleEventTimeout(100ms);
3575 std::this_thread::sleep_for(100ms);
3576
3577 // It shouldn't be dropped by the dispatcher, even though it's stale.
3578 mDispatcher->notifyMotion(hoverExit);
3579 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3580
3581 // Stylus starts hovering again! There should be no crash.
3582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3583 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3584 .build());
3585 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3586}
3587
3588/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003589 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3590 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3591 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3592 * While the mouse is down, new move events from the touch device should be ignored.
3593 */
3594TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3596 sp<FakeWindowHandle> spyWindow =
3597 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3598 spyWindow->setFrame(Rect(0, 0, 200, 200));
3599 spyWindow->setTrustedOverlay(true);
3600 spyWindow->setSpy(true);
3601 sp<FakeWindowHandle> window =
3602 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3603 window->setFrame(Rect(0, 0, 200, 200));
3604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003605 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003606
3607 const int32_t mouseDeviceId = 7;
3608 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003609
3610 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3612 .deviceId(mouseDeviceId)
3613 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3614 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003615 spyWindow->consumeMotionEvent(
3616 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3617 window->consumeMotionEvent(
3618 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3619
3620 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3622 .deviceId(touchDeviceId)
3623 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3624 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003625 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3626 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3627 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3628 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3629
Prabir Pradhan678438e2023-04-13 19:32:51 +00003630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3631 .deviceId(touchDeviceId)
3632 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3633 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003634 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3635 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3636
3637 // Pilfer the stream
3638 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3639 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3640
Prabir Pradhan678438e2023-04-13 19:32:51 +00003641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3642 .deviceId(touchDeviceId)
3643 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3644 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003645 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3646
3647 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3649 .deviceId(mouseDeviceId)
3650 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3651 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3652 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003653
3654 spyWindow->consumeMotionEvent(
3655 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3656 spyWindow->consumeMotionEvent(
3657 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3658 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3659
Prabir Pradhan678438e2023-04-13 19:32:51 +00003660 mDispatcher->notifyMotion(
3661 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3662 .deviceId(mouseDeviceId)
3663 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3664 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3665 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3666 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003667 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3668 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3669
3670 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3672 .deviceId(mouseDeviceId)
3673 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3674 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3675 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003676 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3677 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3678
3679 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3681 .deviceId(touchDeviceId)
3682 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3683 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003684
3685 // No more events
3686 spyWindow->assertNoEvents();
3687 window->assertNoEvents();
3688}
3689
3690/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003691 * On the display, have a single window, and also an area where there's no window.
3692 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3693 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3694 */
3695TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3697 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003698 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003699
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003700 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003701
3702 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003703 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003704
3705 mDispatcher->waitForIdle();
3706 window->assertNoEvents();
3707
3708 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003709 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003710 mDispatcher->waitForIdle();
3711 window->consumeMotionDown();
3712}
3713
3714/**
3715 * Same test as above, but instead of touching the empty space, the first touch goes to
3716 * non-touchable window.
3717 */
3718TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3720 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003721 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003722 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3723 window1->setTouchable(false);
3724 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003725 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003726 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003728 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003729
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003730 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003731 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003732
3733 mDispatcher->waitForIdle();
3734 window1->assertNoEvents();
3735 window2->assertNoEvents();
3736
3737 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003739 mDispatcher->waitForIdle();
3740 window2->consumeMotionDown();
3741}
3742
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003743/**
3744 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3745 * to the event time of the first ACTION_DOWN sent to the particular window.
3746 */
3747TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3749 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003750 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003751 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3752 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003753 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003754 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3755
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003756 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003757
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003758 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003759 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003760
3761 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003762
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003763 const MotionEvent& motionEvent1 = window1->consumeMotionEvent();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003764 window2->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003765 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3766 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003767
3768 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003770 mDispatcher->waitForIdle();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003771 const MotionEvent& motionEvent2 = window2->consumeMotionEvent();
3772 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003773 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003774 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003775
3776 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003777 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003778 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003779 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003780
3781 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003782 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003783 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003784 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003785
3786 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3787 window1->consumeMotionMove();
3788 window1->assertNoEvents();
3789
3790 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003791 mDispatcher->notifyMotion(
3792 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003793 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003794 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003795
Prabir Pradhan678438e2023-04-13 19:32:51 +00003796 mDispatcher->notifyMotion(
3797 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003798 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003799 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003800}
3801
Garfield Tandf26e862020-07-01 20:18:19 -07003802TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003803 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003804 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003805 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003806 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003807 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003808 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003809 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003810
3811 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3812
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003813 mDispatcher->onWindowInfosChanged(
3814 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003815
3816 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003818 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003819 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3820 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003821 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003822 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003823 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003824
3825 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003827 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003828 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3829 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003830 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003831 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003832 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3833 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003834
3835 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003837 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003838 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3839 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003840 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003841 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003842 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3843 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003844
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003846 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003847 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3848 AINPUT_SOURCE_MOUSE)
3849 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3850 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003851 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003852 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003853 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003854
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003856 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003857 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3858 AINPUT_SOURCE_MOUSE)
3859 .buttonState(0)
3860 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003861 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003862 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003863 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003864
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003866 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003867 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3868 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003869 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003870 .build()));
3871 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3872
3873 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003875 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003876 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3877 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003878 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003879 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003880 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003881
3882 // No more events
3883 windowLeft->assertNoEvents();
3884 windowRight->assertNoEvents();
3885}
3886
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003887/**
3888 * Put two fingers down (and don't release them) and click the mouse button.
3889 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3890 * currently active gesture should be canceled, and the new one should proceed.
3891 */
3892TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3894 sp<FakeWindowHandle> window =
3895 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3896 window->setFrame(Rect(0, 0, 600, 800));
3897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003899
3900 const int32_t touchDeviceId = 4;
3901 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003902
3903 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3905 .deviceId(touchDeviceId)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3907 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003908
Prabir Pradhan678438e2023-04-13 19:32:51 +00003909 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3910 .deviceId(touchDeviceId)
3911 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3912 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3913 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003914 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3915 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3916
3917 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3919 .deviceId(mouseDeviceId)
3920 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3921 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3922 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003923 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3924 WithPointerCount(2u)));
3925 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3926
Prabir Pradhan678438e2023-04-13 19:32:51 +00003927 mDispatcher->notifyMotion(
3928 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3929 .deviceId(mouseDeviceId)
3930 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3931 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3932 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3933 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003934 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3935
3936 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3937 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003938 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3939 .deviceId(touchDeviceId)
3940 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3941 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3942 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003943 window->assertNoEvents();
3944}
3945
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003946TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3948
3949 sp<FakeWindowHandle> spyWindow =
3950 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3951 spyWindow->setFrame(Rect(0, 0, 600, 800));
3952 spyWindow->setTrustedOverlay(true);
3953 spyWindow->setSpy(true);
3954 sp<FakeWindowHandle> window =
3955 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3956 window->setFrame(Rect(0, 0, 600, 800));
3957
3958 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003959 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003960
3961 // Send mouse cursor to the window
3962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003963 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003964 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3965 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003967 .build()));
3968
3969 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3970 WithSource(AINPUT_SOURCE_MOUSE)));
3971 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3972 WithSource(AINPUT_SOURCE_MOUSE)));
3973
3974 window->assertNoEvents();
3975 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003976}
3977
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003978TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3979 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3980
3981 sp<FakeWindowHandle> spyWindow =
3982 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3983 spyWindow->setFrame(Rect(0, 0, 600, 800));
3984 spyWindow->setTrustedOverlay(true);
3985 spyWindow->setSpy(true);
3986 sp<FakeWindowHandle> window =
3987 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3988 window->setFrame(Rect(0, 0, 600, 800));
3989
3990 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003991 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003992
3993 // Send mouse cursor to the window
3994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003995 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003996 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3997 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003998 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003999 .build()));
4000
4001 // Move mouse cursor
4002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004003 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004004 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4005 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004006 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004007 .build()));
4008
4009 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4010 WithSource(AINPUT_SOURCE_MOUSE)));
4011 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4012 WithSource(AINPUT_SOURCE_MOUSE)));
4013 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4014 WithSource(AINPUT_SOURCE_MOUSE)));
4015 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4016 WithSource(AINPUT_SOURCE_MOUSE)));
4017 // Touch down on the window
4018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004019 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004020 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4021 AINPUT_SOURCE_TOUCHSCREEN)
4022 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004023 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004024 .build()));
4025 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4026 WithSource(AINPUT_SOURCE_MOUSE)));
4027 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4028 WithSource(AINPUT_SOURCE_MOUSE)));
4029 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4030 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4031 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4032 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4033
4034 // pilfer the motion, retaining the gesture on the spy window.
4035 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4036 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4037 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4038
4039 // Touch UP on the window
4040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004041 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004042 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4043 AINPUT_SOURCE_TOUCHSCREEN)
4044 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004045 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004046 .build()));
4047 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4048 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4049
4050 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4051 // to send a new gesture. It should again go to both windows (spy and the window below), just
4052 // like the first gesture did, before pilfering. The window configuration has not changed.
4053
4054 // One more tap - DOWN
4055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004056 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004057 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4058 AINPUT_SOURCE_TOUCHSCREEN)
4059 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004060 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004061 .build()));
4062 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4063 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4064 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4065 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4066
4067 // Touch UP on the window
4068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004069 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004070 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4071 AINPUT_SOURCE_TOUCHSCREEN)
4072 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004073 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004074 .build()));
4075 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4076 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4077 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4078 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4079
4080 window->assertNoEvents();
4081 spyWindow->assertNoEvents();
4082}
4083
Garfield Tandf26e862020-07-01 20:18:19 -07004084// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4085// directly in this test.
4086TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004088 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004089 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004090 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004091
4092 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4093
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004094 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004095
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004097 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004098 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4099 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004100 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004101 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004102 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004103 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004105 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004106 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4107 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004108 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004109 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004110 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4111 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004112
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004114 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004115 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4116 AINPUT_SOURCE_MOUSE)
4117 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4118 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004119 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004120 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004121 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004122
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004124 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004125 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4126 AINPUT_SOURCE_MOUSE)
4127 .buttonState(0)
4128 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004129 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004130 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004131 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004132
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004134 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004135 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4136 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004137 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004138 .build()));
4139 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4140
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004141 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4142 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4143 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004144 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004145 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4146 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004147 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004148 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004149 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004150}
4151
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004152/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004153 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4154 * is generated.
4155 */
4156TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4158 sp<FakeWindowHandle> window =
4159 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4160 window->setFrame(Rect(0, 0, 1200, 800));
4161
4162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4163
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004164 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004165
4166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004167 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004168 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4169 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004170 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004171 .build()));
4172 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4173
4174 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004175 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004176 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4177}
4178
4179/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004180 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4181 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004182TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4183 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4184 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4186 sp<FakeWindowHandle> window =
4187 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4188 window->setFrame(Rect(0, 0, 1200, 800));
4189
4190 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4191
4192 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4193
4194 MotionEventBuilder hoverEnterBuilder =
4195 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4196 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4197 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4199 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4201 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4202 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4203 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4204}
4205
4206/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004207 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4208 */
4209TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4210 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4211 sp<FakeWindowHandle> window =
4212 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4213 window->setFrame(Rect(0, 0, 100, 100));
4214
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004215 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004216
4217 const int32_t mouseDeviceId = 7;
4218 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004219
4220 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4222 .deviceId(mouseDeviceId)
4223 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4224 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004225 window->consumeMotionEvent(
4226 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4227
4228 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004229 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4230 .deviceId(touchDeviceId)
4231 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4232 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004233
4234 window->consumeMotionEvent(
4235 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4236 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4237}
4238
4239/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004240 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004241 * The tap causes a HOVER_EXIT event to be generated because the current event
4242 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004243 */
4244TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4245 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4246 sp<FakeWindowHandle> window =
4247 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4248 window->setFrame(Rect(0, 0, 100, 100));
4249
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004250 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004251 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4252 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4253 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004254 ASSERT_NO_FATAL_FAILURE(
4255 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4256 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004257
4258 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004259 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4260 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4261 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004262 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004263 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4264 WithSource(AINPUT_SOURCE_MOUSE))));
4265
4266 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004267 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4268 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4269
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4271 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4272 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004273 ASSERT_NO_FATAL_FAILURE(
4274 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4275 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4276}
4277
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004278TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4280 sp<FakeWindowHandle> windowDefaultDisplay =
4281 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4282 ADISPLAY_ID_DEFAULT);
4283 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4284 sp<FakeWindowHandle> windowSecondDisplay =
4285 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4286 SECOND_DISPLAY_ID);
4287 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4288
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004289 mDispatcher->onWindowInfosChanged(
4290 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004291
4292 // Set cursor position in window in default display and check that hover enter and move
4293 // events are generated.
4294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004295 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004296 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4297 AINPUT_SOURCE_MOUSE)
4298 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004299 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004300 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004301 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004302
4303 // Remove all windows in secondary display and check that no event happens on window in
4304 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004305 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4306
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004307 windowDefaultDisplay->assertNoEvents();
4308
4309 // Move cursor position in window in default display and check that only hover move
4310 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004311 mDispatcher->onWindowInfosChanged(
4312 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004314 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004315 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4316 AINPUT_SOURCE_MOUSE)
4317 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004318 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004319 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004320 windowDefaultDisplay->consumeMotionEvent(
4321 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4322 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004323 windowDefaultDisplay->assertNoEvents();
4324}
4325
Garfield Tan00f511d2019-06-12 16:55:40 -07004326TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004328
4329 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004330 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004331 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004332 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004333 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004334 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004335
4336 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4337
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004338 mDispatcher->onWindowInfosChanged(
4339 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004340
4341 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4342 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004344 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004345 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004346 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004347 windowRight->assertNoEvents();
4348}
4349
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004350TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004352 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4353 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004354 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004355
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004357 setFocusedWindow(window);
4358
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004359 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004360
Prabir Pradhan678438e2023-04-13 19:32:51 +00004361 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004362
4363 // Window should receive key down event.
4364 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4365
4366 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4367 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004368 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004369 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004370}
4371
4372TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004373 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004374 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4375 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004376
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004377 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004378
Prabir Pradhan678438e2023-04-13 19:32:51 +00004379 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4380 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004381
4382 // Window should receive motion down event.
4383 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4384
4385 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4386 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004387 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004388 window->consumeMotionEvent(
4389 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004390}
4391
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004392TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4394 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4395 "Fake Window", ADISPLAY_ID_DEFAULT);
4396
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004397 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004398
4399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4400 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4401 .build());
4402
4403 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4404
4405 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4406 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4407 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4408
4409 // After the device has been reset, a new hovering stream can be sent to the window
4410 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4411 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4412 .build());
4413 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4414}
4415
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004416TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4417 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004418 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4419 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004420 window->setFocusable(true);
4421
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004422 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004423 setFocusedWindow(window);
4424
4425 window->consumeFocusEvent(true);
4426
Prabir Pradhan678438e2023-04-13 19:32:51 +00004427 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004428 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4429 const nsecs_t injectTime = keyArgs.eventTime;
4430 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004431 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004432 // The dispatching time should be always greater than or equal to intercept key timeout.
4433 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4434 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4435 std::chrono::nanoseconds(interceptKeyTimeout).count());
4436}
4437
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004438/**
4439 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4440 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004441TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4442 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004443 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4444 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004445 window->setFocusable(true);
4446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004447 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004448 setFocusedWindow(window);
4449
4450 window->consumeFocusEvent(true);
4451
Prabir Pradhan678438e2023-04-13 19:32:51 +00004452 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004453 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004454
4455 // Set a value that's significantly larger than the default consumption timeout. If the
4456 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4457 mFakePolicy->setInterceptKeyTimeout(600ms);
4458 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4459 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004460 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4461}
4462
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004463/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004464 * Two windows. First is a regular window. Second does not overlap with the first, and has
4465 * WATCH_OUTSIDE_TOUCH.
4466 * Both windows are owned by the same UID.
4467 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4468 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4469 */
4470TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004472 sp<FakeWindowHandle> window =
4473 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004474 window->setFrame(Rect{0, 0, 100, 100});
4475
4476 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004477 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004478 ADISPLAY_ID_DEFAULT);
4479 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4480 outsideWindow->setWatchOutsideTouch(true);
4481 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004482 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004483
4484 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004485 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4486 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4487 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004488 window->consumeMotionDown();
4489 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4490 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4491 outsideWindow->consumeMotionEvent(
4492 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004493
4494 // Ensure outsideWindow doesn't get any more events for the gesture.
4495 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4496 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4497 window->consumeMotionMove();
4498 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004499}
4500
4501/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004502 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4503 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4504 * ACTION_OUTSIDE event is sent per gesture.
4505 */
4506TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4507 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004509 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4510 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004511 window->setWatchOutsideTouch(true);
4512 window->setFrame(Rect{0, 0, 100, 100});
4513 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004514 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4515 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004516 secondWindow->setFrame(Rect{100, 100, 200, 200});
4517 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004518 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4519 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004520 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004521 mDispatcher->onWindowInfosChanged(
4522 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004523
4524 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004525 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4526 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4527 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004528 window->assertNoEvents();
4529 secondWindow->assertNoEvents();
4530
4531 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4532 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004533 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4534 ADISPLAY_ID_DEFAULT,
4535 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004536 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4537 window->consumeMotionEvent(
4538 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004539 secondWindow->consumeMotionDown();
4540 thirdWindow->assertNoEvents();
4541
4542 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4543 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004544 mDispatcher->notifyMotion(
4545 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4546 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004547 window->assertNoEvents();
4548 secondWindow->consumeMotionMove();
4549 thirdWindow->consumeMotionDown();
4550}
4551
Prabir Pradhan814fe082022-07-22 20:22:18 +00004552TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004554 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4555 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004556 window->setFocusable(true);
4557
Patrick Williamsd828f302023-04-28 17:52:08 -05004558 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004559 setFocusedWindow(window);
4560
4561 window->consumeFocusEvent(true);
4562
Prabir Pradhan678438e2023-04-13 19:32:51 +00004563 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4564 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4565 mDispatcher->notifyKey(keyDown);
4566 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004567
4568 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4569 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4570
4571 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004572 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004573
4574 window->consumeFocusEvent(false);
4575
Prabir Pradhan678438e2023-04-13 19:32:51 +00004576 mDispatcher->notifyKey(keyDown);
4577 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004578 window->assertNoEvents();
4579}
4580
Arthur Hung96483742022-11-15 03:30:48 +00004581TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4583 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4584 "Fake Window", ADISPLAY_ID_DEFAULT);
4585 // Ensure window is non-split and have some transform.
4586 window->setPreventSplitting(true);
4587 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004588 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004589
4590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004591 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004592 {50, 50}))
4593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4594 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4595
4596 const MotionEvent secondFingerDownEvent =
4597 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4598 .displayId(ADISPLAY_ID_DEFAULT)
4599 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004600 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4601 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004602 .build();
4603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004604 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004605 InputEventInjectionSync::WAIT_FOR_RESULT))
4606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4607
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004608 const MotionEvent& event = window->consumeMotionEvent();
4609 EXPECT_EQ(POINTER_1_DOWN, event.getAction());
4610 EXPECT_EQ(70, event.getX(0)); // 50 + 20
4611 EXPECT_EQ(90, event.getY(0)); // 50 + 40
4612 EXPECT_EQ(-10, event.getX(1)); // -30 + 20
4613 EXPECT_EQ(-10, event.getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004614}
4615
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004616/**
4617 * Two windows: a splittable and a non-splittable.
4618 * The non-splittable window shouldn't receive any "incomplete" gestures.
4619 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4620 * The second pointer should be dropped because the initial window is splittable, so it won't get
4621 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4622 * "incomplete" gestures.
4623 */
4624TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4626 sp<FakeWindowHandle> leftWindow =
4627 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4628 ADISPLAY_ID_DEFAULT);
4629 leftWindow->setPreventSplitting(false);
4630 leftWindow->setFrame(Rect(0, 0, 100, 100));
4631 sp<FakeWindowHandle> rightWindow =
4632 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4633 ADISPLAY_ID_DEFAULT);
4634 rightWindow->setPreventSplitting(true);
4635 rightWindow->setFrame(Rect(100, 100, 200, 200));
4636 mDispatcher->onWindowInfosChanged(
4637 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4638
4639 // Touch down on left, splittable window
4640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4641 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4642 .build());
4643 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4644
4645 mDispatcher->notifyMotion(
4646 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4647 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4648 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4649 .build());
4650 leftWindow->assertNoEvents();
4651 rightWindow->assertNoEvents();
4652}
4653
Harry Cuttsb166c002023-05-09 13:06:05 +00004654TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4655 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4656 sp<FakeWindowHandle> window =
4657 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4658 window->setFrame(Rect(0, 0, 400, 400));
4659 sp<FakeWindowHandle> trustedOverlay =
4660 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4661 ADISPLAY_ID_DEFAULT);
4662 trustedOverlay->setSpy(true);
4663 trustedOverlay->setTrustedOverlay(true);
4664
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004665 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004666
4667 // Start a three-finger touchpad swipe
4668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4669 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4670 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4671 .build());
4672 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4673 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4674 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4675 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4676 .build());
4677 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4678 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4679 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4680 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4681 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4682 .build());
4683
4684 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4685 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4686 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4687
4688 // Move the swipe a bit
4689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4690 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4691 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4692 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4693 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4694 .build());
4695
4696 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4697
4698 // End the swipe
4699 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4700 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4701 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4702 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4703 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4704 .build());
4705 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4706 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4707 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4708 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4709 .build());
4710 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4711 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4712 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4713 .build());
4714
4715 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4716 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4717 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4718
4719 window->assertNoEvents();
4720}
4721
4722TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4724 sp<FakeWindowHandle> window =
4725 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4726 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004727 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004728
4729 // Start a three-finger touchpad swipe
4730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4731 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4732 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4733 .build());
4734 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4735 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4736 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4737 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4738 .build());
4739 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4740 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4741 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4742 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4743 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4744 .build());
4745
4746 // Move the swipe a bit
4747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4748 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4749 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4750 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4751 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4752 .build());
4753
4754 // End the swipe
4755 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4756 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4757 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4758 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4759 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4760 .build());
4761 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4762 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4763 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4764 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4765 .build());
4766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4767 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4768 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4769 .build());
4770
4771 window->assertNoEvents();
4772}
4773
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004774/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004775 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4776 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004777 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004778 */
4779TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4781 sp<FakeWindowHandle> window =
4782 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4783 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004784 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004785
4786 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4788 .downTime(baseTime + 10)
4789 .eventTime(baseTime + 10)
4790 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4791 .build());
4792
4793 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4794
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004795 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004796 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004797
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004799
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004800 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4801 .downTime(baseTime + 10)
4802 .eventTime(baseTime + 30)
4803 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4804 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4805 .build());
4806
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004807 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4808
4809 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004810 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4811 .downTime(baseTime + 10)
4812 .eventTime(baseTime + 40)
4813 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4814 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4815 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004816
4817 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4818
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004819 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4820 .downTime(baseTime + 10)
4821 .eventTime(baseTime + 50)
4822 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4823 .build());
4824
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004825 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4826
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4828 .downTime(baseTime + 60)
4829 .eventTime(baseTime + 60)
4830 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4831 .build());
4832
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004833 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004834}
4835
4836/**
Hu Guo771a7692023-09-17 20:51:08 +08004837 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4838 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4839 * its coordinates should be converted by the transform of the windows of target screen.
4840 */
4841TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4842 // This case will create a window and a spy window on the default display and mirror
4843 // window on the second display. cancel event is sent through spy window pilferPointers
4844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4845
4846 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4847 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4848 spyWindowDefaultDisplay->setTrustedOverlay(true);
4849 spyWindowDefaultDisplay->setSpy(true);
4850
4851 sp<FakeWindowHandle> windowDefaultDisplay =
4852 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4853 ADISPLAY_ID_DEFAULT);
4854 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4855
4856 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4857 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4858
4859 // Add the windows to the dispatcher
4860 mDispatcher->onWindowInfosChanged(
4861 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4862 *windowSecondDisplay->getInfo()},
4863 {},
4864 0,
4865 0});
4866
4867 // Send down to ADISPLAY_ID_DEFAULT
4868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4870 {100, 100}))
4871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4872
4873 spyWindowDefaultDisplay->consumeMotionDown();
4874 windowDefaultDisplay->consumeMotionDown();
4875
4876 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4877
4878 // windowDefaultDisplay gets cancel
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004879 const MotionEvent& event = windowDefaultDisplay->consumeMotionEvent();
4880 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004881
4882 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4883 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4884 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4885 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004886 EXPECT_EQ(100, event.getX(0));
4887 EXPECT_EQ(100, event.getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004888}
4889
4890/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004891 * Ensure the correct coordinate spaces are used by InputDispatcher.
4892 *
4893 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4894 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4895 * space.
4896 */
4897class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4898public:
4899 void SetUp() override {
4900 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004901 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004902 }
4903
4904 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4905 gui::DisplayInfo info;
4906 info.displayId = displayId;
4907 info.transform = transform;
4908 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004909 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004910 }
4911
4912 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4913 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004914 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004915 }
4916
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004917 void removeAllWindowsAndDisplays() {
4918 mDisplayInfos.clear();
4919 mWindowInfos.clear();
4920 }
4921
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004922 // Set up a test scenario where the display has a scaled projection and there are two windows
4923 // on the display.
4924 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4925 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4926 // respectively.
4927 ui::Transform displayTransform;
4928 displayTransform.set(2, 0, 0, 4);
4929 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4930
4931 std::shared_ptr<FakeApplicationHandle> application =
4932 std::make_shared<FakeApplicationHandle>();
4933
4934 // Add two windows to the display. Their frames are represented in the display space.
4935 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004936 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4937 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004938 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4939 addWindow(firstWindow);
4940
4941 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004942 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4943 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004944 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4945 addWindow(secondWindow);
4946 return {std::move(firstWindow), std::move(secondWindow)};
4947 }
4948
4949private:
4950 std::vector<gui::DisplayInfo> mDisplayInfos;
4951 std::vector<gui::WindowInfo> mWindowInfos;
4952};
4953
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004954TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004955 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4956 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004957 // selected so that if the hit test was performed with the point and the bounds being in
4958 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004959 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4960 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4961 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004962
4963 firstWindow->consumeMotionDown();
4964 secondWindow->assertNoEvents();
4965}
4966
4967// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4968// the event should be treated as being in the logical display space.
4969TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4970 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4971 // Send down to the first window. The point is represented in the logical display space. The
4972 // point is selected so that if the hit test was done in logical display space, then it would
4973 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004974 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004975 PointF{75 * 2, 55 * 4});
4976
4977 firstWindow->consumeMotionDown();
4978 secondWindow->assertNoEvents();
4979}
4980
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004981// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4982// event should be treated as being in the logical display space.
4983TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4984 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4985
4986 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4987 ui::Transform injectedEventTransform;
4988 injectedEventTransform.set(matrix);
4989 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4990 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4991
4992 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4993 .displayId(ADISPLAY_ID_DEFAULT)
4994 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004995 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004996 .x(untransformedPoint.x)
4997 .y(untransformedPoint.y))
4998 .build();
4999 event.transform(matrix);
5000
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005001 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005002 InputEventInjectionSync::WAIT_FOR_RESULT);
5003
5004 firstWindow->consumeMotionDown();
5005 secondWindow->assertNoEvents();
5006}
5007
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005008TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5009 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5010
5011 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005012 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5013 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5014 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005015
5016 firstWindow->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005017 const MotionEvent& event = secondWindow->consumeMotionEvent();
5018 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event.getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005019
5020 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005021 EXPECT_EQ(300, event.getRawX(0));
5022 EXPECT_EQ(880, event.getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005023
5024 // Ensure that the x and y values are in the window's coordinate space.
5025 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5026 // the logical display space. This will be the origin of the window space.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005027 EXPECT_EQ(100, event.getX(0));
5028 EXPECT_EQ(80, event.getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005029}
5030
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005031TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5032 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5033 // The monitor will always receive events in the logical display's coordinate space, because
5034 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005035 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005036
5037 // Send down to the first window.
5038 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5039 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5040 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5041 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5042
5043 // Second pointer goes down on second window.
5044 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5045 ADISPLAY_ID_DEFAULT,
5046 {PointF{50, 100}, PointF{150, 220}}));
5047 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5048 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5049 {1, PointF{300, 880}}};
5050 monitor.consumeMotionEvent(
5051 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5052
5053 mDispatcher->cancelCurrentTouch();
5054
5055 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5056 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5057 monitor.consumeMotionEvent(
5058 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5059}
5060
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005061TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5062 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5063
5064 // Send down to the first window.
5065 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5066 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5067 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5068
5069 // The pointer is transferred to the second window, and the second window receives it in the
5070 // correct coordinate space.
5071 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5072 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5073 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5074}
5075
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005076TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5077 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5078
5079 // Send hover move to the second window, and ensure it shows up as hover enter.
5080 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5081 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5082 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5083 WithCoords(100, 80), WithRawCoords(300, 880)));
5084
5085 // Touch down at the same location and ensure a hover exit is synthesized.
5086 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5087 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5088 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5089 WithRawCoords(300, 880)));
5090 secondWindow->consumeMotionEvent(
5091 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5092 secondWindow->assertNoEvents();
5093 firstWindow->assertNoEvents();
5094}
5095
Prabir Pradhan453ae732023-10-13 14:30:14 +00005096// Same as above, but while the window is being mirrored.
5097TEST_F(InputDispatcherDisplayProjectionTest,
5098 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5099 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5100
5101 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5102 ui::Transform secondDisplayTransform;
5103 secondDisplayTransform.set(matrix);
5104 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5105
5106 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5107 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5108 addWindow(secondWindowClone);
5109
5110 // Send hover move to the second window, and ensure it shows up as hover enter.
5111 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5112 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5113 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5114 WithCoords(100, 80), WithRawCoords(300, 880)));
5115
5116 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5117 // display.
5118 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5119 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5120 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5121 WithRawCoords(300, 880)));
5122 secondWindow->consumeMotionEvent(
5123 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5124 secondWindow->assertNoEvents();
5125 firstWindow->assertNoEvents();
5126}
5127
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005128TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5129 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5130
5131 // Send hover enter to second window
5132 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5133 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5134 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5135 WithCoords(100, 80), WithRawCoords(300, 880)));
5136
5137 mDispatcher->cancelCurrentTouch();
5138
5139 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5140 WithRawCoords(300, 880)));
5141 secondWindow->assertNoEvents();
5142 firstWindow->assertNoEvents();
5143}
5144
Prabir Pradhan453ae732023-10-13 14:30:14 +00005145// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005146TEST_F(InputDispatcherDisplayProjectionTest,
5147 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5148 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5149
5150 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5151 ui::Transform secondDisplayTransform;
5152 secondDisplayTransform.set(matrix);
5153 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5154
5155 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5156 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5157 addWindow(secondWindowClone);
5158
5159 // Send hover enter to second window
5160 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5161 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5162 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5163 WithCoords(100, 80), WithRawCoords(300, 880),
5164 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5165
5166 mDispatcher->cancelCurrentTouch();
5167
5168 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5169 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5170 WithRawCoords(300, 880),
5171 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5172 secondWindow->assertNoEvents();
5173 firstWindow->assertNoEvents();
5174}
5175
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005176/** Ensure consistent behavior of InputDispatcher in all orientations. */
5177class InputDispatcherDisplayOrientationFixture
5178 : public InputDispatcherDisplayProjectionTest,
5179 public ::testing::WithParamInterface<ui::Rotation> {};
5180
5181// This test verifies the touchable region of a window for all rotations of the display by tapping
5182// in different locations on the display, specifically points close to the four corners of a
5183// window.
5184TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5185 constexpr static int32_t displayWidth = 400;
5186 constexpr static int32_t displayHeight = 800;
5187
5188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5189
5190 const auto rotation = GetParam();
5191
5192 // Set up the display with the specified rotation.
5193 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5194 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5195 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5196 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5197 logicalDisplayWidth, logicalDisplayHeight);
5198 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5199
5200 // Create a window with its bounds determined in the logical display.
5201 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5202 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5203 sp<FakeWindowHandle> window =
5204 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5205 window->setFrame(frameInDisplay, displayTransform);
5206 addWindow(window);
5207
5208 // The following points in logical display space should be inside the window.
5209 static const std::array<vec2, 4> insidePoints{
5210 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5211 for (const auto pointInsideWindow : insidePoints) {
5212 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5213 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005214 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5215 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5216 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005217 window->consumeMotionDown();
5218
Prabir Pradhan678438e2023-04-13 19:32:51 +00005219 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5220 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5221 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005222 window->consumeMotionUp();
5223 }
5224
5225 // The following points in logical display space should be outside the window.
5226 static const std::array<vec2, 5> outsidePoints{
5227 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5228 for (const auto pointOutsideWindow : outsidePoints) {
5229 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5230 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005231 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5232 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5233 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005234
Prabir Pradhan678438e2023-04-13 19:32:51 +00005235 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5236 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5237 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005238 }
5239 window->assertNoEvents();
5240}
5241
5242// Run the precision tests for all rotations.
5243INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5244 InputDispatcherDisplayOrientationFixture,
5245 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5246 ui::ROTATION_270),
5247 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5248 return ftl::enum_string(testParamInfo.param);
5249 });
5250
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005251using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5252 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005253
5254class TransferTouchFixture : public InputDispatcherTest,
5255 public ::testing::WithParamInterface<TransferFunction> {};
5256
5257TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005259
5260 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005261 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005262 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5263 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005264 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005265 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005266 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5267 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005268 sp<FakeWindowHandle> wallpaper =
5269 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5270 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005271 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005272 mDispatcher->onWindowInfosChanged(
5273 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005274
5275 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005276 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5277 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005278
Svet Ganov5d3bc372020-01-26 23:11:07 -08005279 // Only the first window should get the down event
5280 firstWindow->consumeMotionDown();
5281 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005282 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005283
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005284 // Transfer touch to the second window
5285 TransferFunction f = GetParam();
5286 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5287 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005288 // The first window gets cancel and the second gets down
5289 firstWindow->consumeMotionCancel();
5290 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005291 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005292
5293 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5295 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005296 // The first window gets no events and the second gets up
5297 firstWindow->assertNoEvents();
5298 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005299 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005300}
5301
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005302/**
5303 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5304 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5305 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5306 * natural to the user.
5307 * In this test, we are sending a pointer to both spy window and first window. We then try to
5308 * transfer touch to the second window. The dispatcher should identify the first window as the
5309 * one that should lose the gesture, and therefore the action should be to move the gesture from
5310 * the first window to the second.
5311 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5312 * the other API, as well.
5313 */
5314TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5315 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5316
5317 // Create a couple of windows + a spy window
5318 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005319 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005320 spyWindow->setTrustedOverlay(true);
5321 spyWindow->setSpy(true);
5322 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005323 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005324 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005325 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005326
5327 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005328 mDispatcher->onWindowInfosChanged(
5329 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005330
5331 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005332 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5333 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005334 // Only the first window and spy should get the down event
5335 spyWindow->consumeMotionDown();
5336 firstWindow->consumeMotionDown();
5337
5338 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5339 // if f === 'transferTouch'.
5340 TransferFunction f = GetParam();
5341 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5342 ASSERT_TRUE(success);
5343 // The first window gets cancel and the second gets down
5344 firstWindow->consumeMotionCancel();
5345 secondWindow->consumeMotionDown();
5346
5347 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005348 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5349 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005350 // The first window gets no events and the second+spy get up
5351 firstWindow->assertNoEvents();
5352 spyWindow->consumeMotionUp();
5353 secondWindow->consumeMotionUp();
5354}
5355
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005356TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005357 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005358
5359 PointF touchPoint = {10, 10};
5360
5361 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005362 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005363 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5364 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005365 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005366 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005367 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5368 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005369 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005370
5371 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005372 mDispatcher->onWindowInfosChanged(
5373 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005374
5375 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005376 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5377 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5378 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005379 // Only the first window should get the down event
5380 firstWindow->consumeMotionDown();
5381 secondWindow->assertNoEvents();
5382
5383 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005384 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5385 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005386 // Only the first window should get the pointer down event
5387 firstWindow->consumeMotionPointerDown(1);
5388 secondWindow->assertNoEvents();
5389
5390 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005391 TransferFunction f = GetParam();
5392 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5393 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005394 // The first window gets cancel and the second gets down and pointer down
5395 firstWindow->consumeMotionCancel();
5396 secondWindow->consumeMotionDown();
5397 secondWindow->consumeMotionPointerDown(1);
5398
5399 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005400 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5401 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005402 // The first window gets nothing and the second gets pointer up
5403 firstWindow->assertNoEvents();
5404 secondWindow->consumeMotionPointerUp(1);
5405
5406 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005407 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5408 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005409 // The first window gets nothing and the second gets up
5410 firstWindow->assertNoEvents();
5411 secondWindow->consumeMotionUp();
5412}
5413
Arthur Hungc539dbb2022-12-08 07:45:36 +00005414TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5416
5417 // Create a couple of windows
5418 sp<FakeWindowHandle> firstWindow =
5419 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5420 ADISPLAY_ID_DEFAULT);
5421 firstWindow->setDupTouchToWallpaper(true);
5422 sp<FakeWindowHandle> secondWindow =
5423 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5424 ADISPLAY_ID_DEFAULT);
5425 secondWindow->setDupTouchToWallpaper(true);
5426
5427 sp<FakeWindowHandle> wallpaper1 =
5428 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5429 wallpaper1->setIsWallpaper(true);
5430
5431 sp<FakeWindowHandle> wallpaper2 =
5432 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5433 wallpaper2->setIsWallpaper(true);
5434 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005435 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5436 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5437 {},
5438 0,
5439 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005440
5441 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005442 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5443 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005444
5445 // Only the first window should get the down event
5446 firstWindow->consumeMotionDown();
5447 secondWindow->assertNoEvents();
5448 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5449 wallpaper2->assertNoEvents();
5450
5451 // Transfer touch focus to the second window
5452 TransferFunction f = GetParam();
5453 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5454 ASSERT_TRUE(success);
5455
5456 // The first window gets cancel and the second gets down
5457 firstWindow->consumeMotionCancel();
5458 secondWindow->consumeMotionDown();
5459 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5460 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5461
5462 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005463 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5464 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005465 // The first window gets no events and the second gets up
5466 firstWindow->assertNoEvents();
5467 secondWindow->consumeMotionUp();
5468 wallpaper1->assertNoEvents();
5469 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5470}
5471
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005472// For the cases of single pointer touch and two pointers non-split touch, the api's
5473// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5474// for the case where there are multiple pointers split across several windows.
5475INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5476 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005477 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5478 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005479 return dispatcher->transferTouch(destChannelToken,
5480 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005481 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005482 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5483 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005484 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005485 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005486 }));
5487
Svet Ganov5d3bc372020-01-26 23:11:07 -08005488TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005489 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005490
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005491 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005492 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5493 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005494 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005495
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005496 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005497 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5498 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005499 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005500
5501 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005502 mDispatcher->onWindowInfosChanged(
5503 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005504
5505 PointF pointInFirst = {300, 200};
5506 PointF pointInSecond = {300, 600};
5507
5508 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005509 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5510 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5511 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005512 // Only the first window should get the down event
5513 firstWindow->consumeMotionDown();
5514 secondWindow->assertNoEvents();
5515
5516 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005517 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5518 ADISPLAY_ID_DEFAULT,
5519 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005520 // The first window gets a move and the second a down
5521 firstWindow->consumeMotionMove();
5522 secondWindow->consumeMotionDown();
5523
5524 // Transfer touch focus to the second window
5525 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5526 // The first window gets cancel and the new gets pointer down (it already saw down)
5527 firstWindow->consumeMotionCancel();
5528 secondWindow->consumeMotionPointerDown(1);
5529
5530 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005531 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5532 ADISPLAY_ID_DEFAULT,
5533 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005534 // The first window gets nothing and the second gets pointer up
5535 firstWindow->assertNoEvents();
5536 secondWindow->consumeMotionPointerUp(1);
5537
5538 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005539 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5540 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005541 // The first window gets nothing and the second gets up
5542 firstWindow->assertNoEvents();
5543 secondWindow->consumeMotionUp();
5544}
5545
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005546// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5547// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5548// touch is not supported, so the touch should continue on those windows and the transferred-to
5549// window should get nothing.
5550TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5552
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005553 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005554 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5555 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005556 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005557
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005558 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005559 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5560 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005561 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005562
5563 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005564 mDispatcher->onWindowInfosChanged(
5565 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005566
5567 PointF pointInFirst = {300, 200};
5568 PointF pointInSecond = {300, 600};
5569
5570 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005571 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5572 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5573 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005574 // Only the first window should get the down event
5575 firstWindow->consumeMotionDown();
5576 secondWindow->assertNoEvents();
5577
5578 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005579 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5580 ADISPLAY_ID_DEFAULT,
5581 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005582 // The first window gets a move and the second a down
5583 firstWindow->consumeMotionMove();
5584 secondWindow->consumeMotionDown();
5585
5586 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005587 const bool transferred =
5588 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005589 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5590 ASSERT_FALSE(transferred);
5591 firstWindow->assertNoEvents();
5592 secondWindow->assertNoEvents();
5593
5594 // The rest of the dispatch should proceed as normal
5595 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005596 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5597 ADISPLAY_ID_DEFAULT,
5598 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005599 // The first window gets MOVE and the second gets pointer up
5600 firstWindow->consumeMotionMove();
5601 secondWindow->consumeMotionUp();
5602
5603 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005604 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5605 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005606 // The first window gets nothing and the second gets up
5607 firstWindow->consumeMotionUp();
5608 secondWindow->assertNoEvents();
5609}
5610
Arthur Hungabbb9d82021-09-01 14:52:30 +00005611// This case will create two windows and one mirrored window on the default display and mirror
5612// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5613// the windows info of second display before default display.
5614TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5616 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005617 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005618 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005619 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005620 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005621 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005622
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005623 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005624 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005625
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005626 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005627 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005628
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005629 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005630 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005631
5632 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005633 mDispatcher->onWindowInfosChanged(
5634 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5635 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5636 *secondWindowInPrimary->getInfo()},
5637 {},
5638 0,
5639 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005640
5641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005642 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005643 {50, 50}))
5644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5645
5646 // Window should receive motion event.
5647 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5648
5649 // Transfer touch focus
5650 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5651 secondWindowInPrimary->getToken()));
5652 // The first window gets cancel.
5653 firstWindowInPrimary->consumeMotionCancel();
5654 secondWindowInPrimary->consumeMotionDown();
5655
5656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005657 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005658 ADISPLAY_ID_DEFAULT, {150, 50}))
5659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5660 firstWindowInPrimary->assertNoEvents();
5661 secondWindowInPrimary->consumeMotionMove();
5662
5663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005664 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005665 {150, 50}))
5666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5667 firstWindowInPrimary->assertNoEvents();
5668 secondWindowInPrimary->consumeMotionUp();
5669}
5670
5671// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5672// 'transferTouch' api.
5673TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5675 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005676 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005677 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005678 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005679 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005680 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005681
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005682 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005683 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005684
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005685 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005686 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005687
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005688 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005689 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005690
5691 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005692 mDispatcher->onWindowInfosChanged(
5693 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5694 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5695 *secondWindowInPrimary->getInfo()},
5696 {},
5697 0,
5698 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005699
5700 // Touch on second display.
5701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5703 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5705
5706 // Window should receive motion event.
5707 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5708
5709 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005710 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005711
5712 // The first window gets cancel.
5713 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5714 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5715
5716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005717 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005718 SECOND_DISPLAY_ID, {150, 50}))
5719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5720 firstWindowInPrimary->assertNoEvents();
5721 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5722
5723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005724 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5726 firstWindowInPrimary->assertNoEvents();
5727 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5728}
5729
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005730TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5733 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005734
Vishnu Nair47074b82020-08-14 11:54:47 -07005735 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005737 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005738
5739 window->consumeFocusEvent(true);
5740
Prabir Pradhan678438e2023-04-13 19:32:51 +00005741 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005742
5743 // Window should receive key down event.
5744 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005745
5746 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005747 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005748 mFakePolicy->assertUserActivityPoked();
5749}
5750
5751TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5753 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5754 "Fake Window", ADISPLAY_ID_DEFAULT);
5755
5756 window->setDisableUserActivity(true);
5757 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005758 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005759 setFocusedWindow(window);
5760
5761 window->consumeFocusEvent(true);
5762
5763 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5764
5765 // Window should receive key down event.
5766 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5767
5768 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005769 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005770 mFakePolicy->assertUserActivityNotPoked();
5771}
5772
5773TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5775 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5776 "Fake Window", ADISPLAY_ID_DEFAULT);
5777
5778 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005779 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005780 setFocusedWindow(window);
5781
5782 window->consumeFocusEvent(true);
5783
5784 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5785 mDispatcher->waitForIdle();
5786
5787 // System key is not passed down
5788 window->assertNoEvents();
5789
5790 // Should have poked user activity
5791 mFakePolicy->assertUserActivityPoked();
5792}
5793
5794TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5797 "Fake Window", ADISPLAY_ID_DEFAULT);
5798
5799 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005800 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005801 setFocusedWindow(window);
5802
5803 window->consumeFocusEvent(true);
5804
5805 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5806 mDispatcher->waitForIdle();
5807
5808 // System key is not passed down
5809 window->assertNoEvents();
5810
5811 // Should have poked user activity
5812 mFakePolicy->assertUserActivityPoked();
5813}
5814
5815TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5817 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5818 "Fake Window", ADISPLAY_ID_DEFAULT);
5819
5820 window->setDisableUserActivity(true);
5821 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005822 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005823 setFocusedWindow(window);
5824
5825 window->consumeFocusEvent(true);
5826
5827 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5828 mDispatcher->waitForIdle();
5829
5830 // System key is not passed down
5831 window->assertNoEvents();
5832
5833 // Should have poked user activity
5834 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005835}
5836
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005837TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5839 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5840 "Fake Window", ADISPLAY_ID_DEFAULT);
5841
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005842 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005843
5844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005845 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005846 ADISPLAY_ID_DEFAULT, {100, 100}))
5847 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5848
5849 window->consumeMotionEvent(
5850 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5851
5852 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005853 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005854 mFakePolicy->assertUserActivityPoked();
5855}
5856
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005857TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005859 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5860 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005861
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005862 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005863
Prabir Pradhan678438e2023-04-13 19:32:51 +00005864 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005865 mDispatcher->waitForIdle();
5866
5867 window->assertNoEvents();
5868}
5869
5870// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5871TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005873 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5874 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005875
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005876 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005877
5878 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005879 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005880 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005881 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5882 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005883
5884 // Window should receive only the motion event
5885 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5886 window->assertNoEvents(); // Key event or focus event will not be received
5887}
5888
arthurhungea3f4fc2020-12-21 23:18:53 +08005889TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5891
arthurhungea3f4fc2020-12-21 23:18:53 +08005892 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005893 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5894 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005895 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005896
arthurhungea3f4fc2020-12-21 23:18:53 +08005897 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005898 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5899 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005900 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005901
5902 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005903 mDispatcher->onWindowInfosChanged(
5904 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005905
5906 PointF pointInFirst = {300, 200};
5907 PointF pointInSecond = {300, 600};
5908
5909 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005910 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5911 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5912 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005913 // Only the first window should get the down event
5914 firstWindow->consumeMotionDown();
5915 secondWindow->assertNoEvents();
5916
5917 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005918 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5919 ADISPLAY_ID_DEFAULT,
5920 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005921 // The first window gets a move and the second a down
5922 firstWindow->consumeMotionMove();
5923 secondWindow->consumeMotionDown();
5924
5925 // Send pointer cancel to the second window
5926 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005927 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005928 {pointInFirst, pointInSecond});
5929 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005930 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005931 // The first window gets move and the second gets cancel.
5932 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5933 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5934
5935 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005936 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5937 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005938 // The first window gets up and the second gets nothing.
5939 firstWindow->consumeMotionUp();
5940 secondWindow->assertNoEvents();
5941}
5942
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005943TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5945
5946 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005947 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005948 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005949 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5950 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5951 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5952
Harry Cutts33476232023-01-30 19:57:29 +00005953 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005954 window->assertNoEvents();
5955 mDispatcher->waitForIdle();
5956}
5957
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005958using InputDispatcherMonitorTest = InputDispatcherTest;
5959
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005960/**
5961 * Two entities that receive touch: A window, and a global monitor.
5962 * The touch goes to the window, and then the window disappears.
5963 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5964 * for the monitor, as well.
5965 * 1. foregroundWindow
5966 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5967 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005968TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5970 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005971 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005972
Prabir Pradhanfb549072023-10-05 19:17:36 +00005973 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005974
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005975 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005977 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005978 {100, 200}))
5979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5980
5981 // Both the foreground window and the global monitor should receive the touch down
5982 window->consumeMotionDown();
5983 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5984
5985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005986 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005987 ADISPLAY_ID_DEFAULT, {110, 200}))
5988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5989
5990 window->consumeMotionMove();
5991 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5992
5993 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005994 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005995 window->consumeMotionCancel();
5996 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5997
5998 // If more events come in, there will be no more foreground window to send them to. This will
5999 // cause a cancel for the monitor, as well.
6000 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006001 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006002 ADISPLAY_ID_DEFAULT, {120, 200}))
6003 << "Injection should fail because the window was removed";
6004 window->assertNoEvents();
6005 // Global monitor now gets the cancel
6006 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6007}
6008
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006009TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006011 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6012 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006013 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006014
Prabir Pradhanfb549072023-10-05 19:17:36 +00006015 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006016
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006018 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006020 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006021 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006022}
6023
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006024TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006025 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006026
Chris Yea209fde2020-07-22 13:54:51 -07006027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006028 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6029 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006030 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006031
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006033 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006035 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006036 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006037
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006038 // Pilfer pointers from the monitor.
6039 // This should not do anything and the window should continue to receive events.
6040 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006041
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006043 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006044 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006045 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006046
6047 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6048 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006049}
6050
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006051TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006053 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6054 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006055 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006056 window->setWindowOffset(20, 40);
6057 window->setWindowTransform(0, 1, -1, 0);
6058
Prabir Pradhanfb549072023-10-05 19:17:36 +00006059 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006060
6061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006062 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6064 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6065 MotionEvent* event = monitor.consumeMotion();
6066 // Even though window has transform, gesture monitor must not.
6067 ASSERT_EQ(ui::Transform(), event->getTransform());
6068}
6069
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006070TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006072 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006073
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006074 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006075 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006076 << "Injection should fail if there is a monitor, but no touchable window";
6077 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006078}
6079
chaviw81e2bb92019-12-18 15:03:51 -08006080TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006082 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6083 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006084
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006085 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006086
6087 NotifyMotionArgs motionArgs =
6088 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6089 ADISPLAY_ID_DEFAULT);
6090
Prabir Pradhan678438e2023-04-13 19:32:51 +00006091 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006092 // Window should receive motion down event.
6093 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6094
6095 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006096 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006097 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6098 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6099 motionArgs.pointerCoords[0].getX() - 10);
6100
Prabir Pradhan678438e2023-04-13 19:32:51 +00006101 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006102 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006103}
6104
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006105/**
6106 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6107 * the device default right away. In the test scenario, we check both the default value,
6108 * and the action of enabling / disabling.
6109 */
6110TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006112 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6113 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006114 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006115
6116 // Set focused application.
6117 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006118 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006119
6120 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006121 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006122 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006123 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006124
6125 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006126 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006127 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006128 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006129
6130 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006131 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006132 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006133 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006134 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006135 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006136 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006137 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006138
6139 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006140 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006141 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006142 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006143
6144 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006145 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006146 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006147 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006148 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006149 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006150 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006151 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006152
6153 window->assertNoEvents();
6154}
6155
Gang Wange9087892020-01-07 12:17:14 -05006156TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006157 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006158 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6159 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006160
6161 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006162 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006163
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006164 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006165 setFocusedWindow(window);
6166
Harry Cutts33476232023-01-30 19:57:29 +00006167 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006168
Prabir Pradhan678438e2023-04-13 19:32:51 +00006169 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6170 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006171
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006172 const KeyEvent& event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006173
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006174 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Gang Wange9087892020-01-07 12:17:14 -05006175 ASSERT_NE(verified, nullptr);
6176 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6177
6178 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6179 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6180 ASSERT_EQ(keyArgs.source, verified->source);
6181 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6182
6183 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6184
6185 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006186 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006187 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006188 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6189 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6190 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6191 ASSERT_EQ(0, verifiedKey.repeatCount);
6192}
6193
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006194TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006196 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6197 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006198
6199 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6200
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006201 ui::Transform transform;
6202 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6203
6204 gui::DisplayInfo displayInfo;
6205 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6206 displayInfo.transform = transform;
6207
Patrick Williamsd828f302023-04-28 17:52:08 -05006208 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006209
Prabir Pradhan678438e2023-04-13 19:32:51 +00006210 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006211 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6212 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006213 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006214
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006215 const MotionEvent& event = window->consumeMotionEvent();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006216
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006217 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006218 ASSERT_NE(verified, nullptr);
6219 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6220
6221 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6222 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6223 EXPECT_EQ(motionArgs.source, verified->source);
6224 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6225
6226 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6227
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006228 const vec2 rawXY =
6229 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6230 motionArgs.pointerCoords[0].getXYValue());
6231 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6232 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006233 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006234 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006235 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006236 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6237 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6238}
6239
chaviw09c8d2d2020-08-24 15:48:26 -07006240/**
6241 * Ensure that separate calls to sign the same data are generating the same key.
6242 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6243 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6244 * tests.
6245 */
6246TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6247 KeyEvent event = getTestKeyEvent();
6248 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6249
6250 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6251 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6252 ASSERT_EQ(hmac1, hmac2);
6253}
6254
6255/**
6256 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6257 */
6258TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6259 KeyEvent event = getTestKeyEvent();
6260 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6261 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6262
6263 verifiedEvent.deviceId += 1;
6264 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6265
6266 verifiedEvent.source += 1;
6267 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6268
6269 verifiedEvent.eventTimeNanos += 1;
6270 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6271
6272 verifiedEvent.displayId += 1;
6273 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6274
6275 verifiedEvent.action += 1;
6276 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6277
6278 verifiedEvent.downTimeNanos += 1;
6279 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6280
6281 verifiedEvent.flags += 1;
6282 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6283
6284 verifiedEvent.keyCode += 1;
6285 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6286
6287 verifiedEvent.scanCode += 1;
6288 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6289
6290 verifiedEvent.metaState += 1;
6291 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6292
6293 verifiedEvent.repeatCount += 1;
6294 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6295}
6296
Vishnu Nair958da932020-08-21 17:12:37 -07006297TEST_F(InputDispatcherTest, SetFocusedWindow) {
6298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6299 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006300 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006301 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006302 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006303 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6304
6305 // Top window is also focusable but is not granted focus.
6306 windowTop->setFocusable(true);
6307 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006308 mDispatcher->onWindowInfosChanged(
6309 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006310 setFocusedWindow(windowSecond);
6311
6312 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006314 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006315
6316 // Focused window should receive event.
6317 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6318 windowTop->assertNoEvents();
6319}
6320
6321TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6322 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6323 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006324 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006325 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6326
6327 window->setFocusable(true);
6328 // Release channel for window is no longer valid.
6329 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006330 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006331 setFocusedWindow(window);
6332
6333 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006334 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006335
6336 // window channel is invalid, so it should not receive any input event.
6337 window->assertNoEvents();
6338}
6339
6340TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6341 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6342 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006343 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006344 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006345 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6346
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006347 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006348 setFocusedWindow(window);
6349
6350 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006351 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006352
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006353 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006354 window->assertNoEvents();
6355}
6356
6357TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6359 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006360 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006361 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006362 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006363 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6364
6365 windowTop->setFocusable(true);
6366 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006367 mDispatcher->onWindowInfosChanged(
6368 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006369 setFocusedWindow(windowTop);
6370 windowTop->consumeFocusEvent(true);
6371
Chavi Weingarten847e8512023-03-29 00:26:09 +00006372 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006373 mDispatcher->onWindowInfosChanged(
6374 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006375 windowSecond->consumeFocusEvent(true);
6376 windowTop->consumeFocusEvent(false);
6377
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006379 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006380
6381 // Focused window should receive event.
6382 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6383}
6384
Chavi Weingarten847e8512023-03-29 00:26:09 +00006385TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006386 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6387 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006388 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006389 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006390 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006391 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6392
6393 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006394 windowSecond->setFocusable(false);
6395 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006396 mDispatcher->onWindowInfosChanged(
6397 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006398 setFocusedWindow(windowTop);
6399 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006400
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006402 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006403
6404 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006405 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006406 windowSecond->assertNoEvents();
6407}
6408
6409TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6411 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006412 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006413 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006414 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6415 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006416 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6417
6418 window->setFocusable(true);
6419 previousFocusedWindow->setFocusable(true);
6420 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006421 mDispatcher->onWindowInfosChanged(
6422 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006423 setFocusedWindow(previousFocusedWindow);
6424 previousFocusedWindow->consumeFocusEvent(true);
6425
6426 // Requesting focus on invisible window takes focus from currently focused window.
6427 setFocusedWindow(window);
6428 previousFocusedWindow->consumeFocusEvent(false);
6429
6430 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006432 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6433 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006434
6435 // Window does not get focus event or key down.
6436 window->assertNoEvents();
6437
6438 // Window becomes visible.
6439 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006440 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006441
6442 // Window receives focus event.
6443 window->consumeFocusEvent(true);
6444 // Focused window receives key down.
6445 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6446}
6447
Vishnu Nair599f1412021-06-21 10:39:58 -07006448TEST_F(InputDispatcherTest, DisplayRemoved) {
6449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6450 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006451 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006452 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6453
6454 // window is granted focus.
6455 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006456 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006457 setFocusedWindow(window);
6458 window->consumeFocusEvent(true);
6459
6460 // When a display is removed window loses focus.
6461 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6462 window->consumeFocusEvent(false);
6463}
6464
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006465/**
6466 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6467 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6468 * of the 'slipperyEnterWindow'.
6469 *
6470 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6471 * a way so that the touched location is no longer covered by the top window.
6472 *
6473 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6474 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6475 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6476 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6477 * with ACTION_DOWN).
6478 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6479 * window moved itself away from the touched location and had Flag::SLIPPERY.
6480 *
6481 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6482 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6483 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6484 *
6485 * In this test, we ensure that the event received by the bottom window has
6486 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6487 */
6488TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006489 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006490 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006491
6492 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6493 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6494
6495 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006496 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006497 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006498 // Make sure this one overlaps the bottom window
6499 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6500 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6501 // one. Windows with the same owner are not considered to be occluding each other.
6502 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6503
6504 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006505 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006506 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6507
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006508 mDispatcher->onWindowInfosChanged(
6509 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006510
6511 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6513 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6514 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006515 slipperyExitWindow->consumeMotionDown();
6516 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006517 mDispatcher->onWindowInfosChanged(
6518 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006519
Prabir Pradhan678438e2023-04-13 19:32:51 +00006520 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6521 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6522 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006523
6524 slipperyExitWindow->consumeMotionCancel();
6525
6526 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6527 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6528}
6529
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006530/**
6531 * Two windows, one on the left and another on the right. The left window is slippery. The right
6532 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6533 * touch moves from the left window into the right window, the gesture should continue to go to the
6534 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6535 * reproduces a crash.
6536 */
6537TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6538 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6539
6540 sp<FakeWindowHandle> leftSlipperyWindow =
6541 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6542 leftSlipperyWindow->setSlippery(true);
6543 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6544
6545 sp<FakeWindowHandle> rightDropTouchesWindow =
6546 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6547 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6548 rightDropTouchesWindow->setDropInput(true);
6549
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006550 mDispatcher->onWindowInfosChanged(
6551 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006552
6553 // Start touch in the left window
6554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6555 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6556 .build());
6557 leftSlipperyWindow->consumeMotionDown();
6558
6559 // And move it into the right window
6560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6561 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6562 .build());
6563
6564 // Since the right window isn't eligible to receive input, touch does not slip.
6565 // The left window continues to receive the gesture.
6566 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6567 rightDropTouchesWindow->assertNoEvents();
6568}
6569
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006570/**
6571 * A single window is on screen first. Touch is injected into that window. Next, a second window
6572 * appears. Since the first window is slippery, touch will move from the first window to the second.
6573 */
6574TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6576 sp<FakeWindowHandle> originalWindow =
6577 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6578 originalWindow->setFrame(Rect(0, 0, 200, 200));
6579 originalWindow->setSlippery(true);
6580
6581 sp<FakeWindowHandle> appearingWindow =
6582 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6583 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6584
6585 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6586
6587 // Touch down on the original window
6588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6589 injectMotionEvent(*mDispatcher,
6590 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6591 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6592 .build()));
6593 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6594
6595 // Now, a new window appears. This could be, for example, a notification shade that appears
6596 // after user starts to drag down on the launcher window.
6597 mDispatcher->onWindowInfosChanged(
6598 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6600 injectMotionEvent(*mDispatcher,
6601 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6602 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6603 .build()));
6604 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6605 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6607 injectMotionEvent(*mDispatcher,
6608 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6609 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6610 .build()));
6611 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6612
6613 originalWindow->assertNoEvents();
6614 appearingWindow->assertNoEvents();
6615}
6616
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006617TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006618 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6620
6621 sp<FakeWindowHandle> leftWindow =
6622 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6623 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006624 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006625
6626 sp<FakeWindowHandle> rightSpy =
6627 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6628 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006629 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006630 rightSpy->setSpy(true);
6631 rightSpy->setTrustedOverlay(true);
6632
6633 sp<FakeWindowHandle> rightWindow =
6634 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6635 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006636 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006637
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006638 mDispatcher->onWindowInfosChanged(
6639 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006640
6641 // Touch in the left window
6642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6643 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6644 .build());
6645 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6646 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006647 ASSERT_NO_FATAL_FAILURE(
6648 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006649
6650 // Touch another finger over the right windows
6651 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6652 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6653 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6654 .build());
6655 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6656 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6657 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6658 mDispatcher->waitForIdle();
6659 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006660 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6661 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006662
6663 // Release finger over left window. The UP actions are not treated as device interaction.
6664 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6665 // is part of the UP action, we do not treat this as device interaction.
6666 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6667 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6668 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6669 .build());
6670 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6671 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6672 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6673 mDispatcher->waitForIdle();
6674 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6675
6676 // Move remaining finger
6677 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6678 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6679 .build());
6680 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6681 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6682 mDispatcher->waitForIdle();
6683 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006684 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006685
6686 // Release all fingers
6687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6688 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6689 .build());
6690 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6691 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6692 mDispatcher->waitForIdle();
6693 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6694}
6695
6696TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6698
6699 sp<FakeWindowHandle> window =
6700 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6701 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006702 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006703
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006704 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006705 setFocusedWindow(window);
6706 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6707
6708 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6709 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6710 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006711 ASSERT_NO_FATAL_FAILURE(
6712 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006713
6714 // The UP actions are not treated as device interaction.
6715 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6716 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6717 mDispatcher->waitForIdle();
6718 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6719}
6720
Prabir Pradhan5893d362023-11-17 04:30:40 +00006721TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6723
6724 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6725 ADISPLAY_ID_DEFAULT);
6726 left->setFrame(Rect(0, 0, 100, 100));
6727 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6728 "Right Window", ADISPLAY_ID_DEFAULT);
6729 right->setFrame(Rect(100, 0, 200, 100));
6730 sp<FakeWindowHandle> spy =
6731 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6732 spy->setFrame(Rect(0, 0, 200, 100));
6733 spy->setTrustedOverlay(true);
6734 spy->setSpy(true);
6735
6736 mDispatcher->onWindowInfosChanged(
6737 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6738
6739 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6740 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6741 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6742 mDispatcher->notifyMotion(notifyArgs);
6743
6744 const MotionEvent& leftEnter = left->consumeMotionEvent(
6745 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6746 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6747
6748 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6749 Not(WithEventId(notifyArgs.id)),
6750 Not(WithEventId(leftEnter.getId())),
6751 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6752
6753 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6754 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6755 {PointF{150, 50}});
6756 mDispatcher->notifyMotion(notifyArgs);
6757
6758 const MotionEvent& leftExit = left->consumeMotionEvent(
6759 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6760 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6761
6762 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6763 Not(WithEventId(notifyArgs.id)),
6764 Not(WithEventId(leftExit.getId())),
6765 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6766
6767 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6768}
6769
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006770class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6771protected:
6772 std::shared_ptr<FakeApplicationHandle> mApp;
6773 sp<FakeWindowHandle> mWindow;
6774
6775 virtual void SetUp() override {
6776 InputDispatcherTest::SetUp();
6777
6778 mApp = std::make_shared<FakeApplicationHandle>();
6779
6780 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6781 mWindow->setFrame(Rect(0, 0, 100, 100));
6782
6783 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6784 setFocusedWindow(mWindow);
6785 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6786 }
6787
6788 void setFallback(int32_t keycode) {
6789 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6790 return KeyEventBuilder(event).keyCode(keycode).build();
6791 });
6792 }
6793
6794 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006795 const KeyEvent& event = mWindow->consumeKey(handled);
6796 ASSERT_THAT(event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006797 }
6798};
6799
6800TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6801 mDispatcher->notifyKey(
6802 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6803 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6804 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6805}
6806
6807TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6808 mDispatcher->notifyKey(
6809 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6810 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6811 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6812}
6813
6814TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6815 mDispatcher->notifyKey(
6816 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6817
6818 // Do not handle this key event.
6819 consumeKey(/*handled=*/false,
6820 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6821 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6822
6823 // Since the policy did not request any fallback to be generated, ensure there are no events.
6824 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6825}
6826
6827TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6828 setFallback(AKEYCODE_B);
6829 mDispatcher->notifyKey(
6830 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6831
6832 // Do not handle this key event.
6833 consumeKey(/*handled=*/false,
6834 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6835
6836 // Since the key was not handled, ensure the fallback event was dispatched instead.
6837 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6838 consumeKey(/*handled=*/true,
6839 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6840 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6841
6842 // Release the original key, and ensure the fallback key is also released.
6843 mDispatcher->notifyKey(
6844 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6845 consumeKey(/*handled=*/false,
6846 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6847 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6848 consumeKey(/*handled=*/true,
6849 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6850 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6851
6852 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6853 mWindow->assertNoEvents();
6854}
6855
6856TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6857 setFallback(AKEYCODE_B);
6858 mDispatcher->notifyKey(
6859 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6860
6861 // Do not handle this key event, but handle the fallback.
6862 consumeKey(/*handled=*/false,
6863 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6864 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6865 consumeKey(/*handled=*/true,
6866 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6867 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6868
6869 // Release the original key, and ensure the fallback key is also released.
6870 mDispatcher->notifyKey(
6871 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6872 // But this time, the app handles the original key.
6873 consumeKey(/*handled=*/true,
6874 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6875 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6876 // Ensure the fallback key is canceled.
6877 consumeKey(/*handled=*/true,
6878 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6879 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6880
6881 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6882 mWindow->assertNoEvents();
6883}
6884
6885TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6886 setFallback(AKEYCODE_B);
6887 mDispatcher->notifyKey(
6888 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6889
6890 // Do not handle this key event.
6891 consumeKey(/*handled=*/false,
6892 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6893 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6894 // App does not handle the fallback either, so ensure another fallback is not generated.
6895 setFallback(AKEYCODE_C);
6896 consumeKey(/*handled=*/false,
6897 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6898 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6899
6900 // Release the original key, and ensure the fallback key is also released.
6901 setFallback(AKEYCODE_B);
6902 mDispatcher->notifyKey(
6903 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6904 consumeKey(/*handled=*/false,
6905 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6906 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6907 consumeKey(/*handled=*/false,
6908 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6909 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6910
6911 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6912 mWindow->assertNoEvents();
6913}
6914
6915TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6916 setFallback(AKEYCODE_B);
6917 mDispatcher->notifyKey(
6918 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6919
6920 // Do not handle this key event, so fallback is generated.
6921 consumeKey(/*handled=*/false,
6922 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6923 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6924 consumeKey(/*handled=*/true,
6925 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6926 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6927
6928 // Release the original key, but assume the policy is misbehaving and it
6929 // generates an inconsistent fallback to the one from the DOWN event.
6930 setFallback(AKEYCODE_C);
6931 mDispatcher->notifyKey(
6932 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6933 consumeKey(/*handled=*/false,
6934 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6935 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6936 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6937 consumeKey(/*handled=*/true,
6938 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6939 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6940
6941 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6942 mWindow->assertNoEvents();
6943}
6944
6945TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6946 setFallback(AKEYCODE_B);
6947 mDispatcher->notifyKey(
6948 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6949
6950 // Do not handle this key event, so fallback is generated.
6951 consumeKey(/*handled=*/false,
6952 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6953 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6954 consumeKey(/*handled=*/true,
6955 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6956 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6957
6958 // The original key is canceled.
6959 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6960 .keyCode(AKEYCODE_A)
6961 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6962 .build());
6963 consumeKey(/*handled=*/false,
6964 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6965 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6966 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6967 // Ensure the fallback key is also canceled due to the original key being canceled.
6968 consumeKey(/*handled=*/true,
6969 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6970 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6971
6972 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6973 mWindow->assertNoEvents();
6974}
6975
Garfield Tan1c7bc862020-01-28 13:24:04 -08006976class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6977protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006978 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6979 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006980
Chris Yea209fde2020-07-22 13:54:51 -07006981 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006982 sp<FakeWindowHandle> mWindow;
6983
6984 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006985 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006986 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006987 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006988 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006989 ASSERT_EQ(OK, mDispatcher->start());
6990
6991 setUpWindow();
6992 }
6993
6994 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006995 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006996 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006997
Vishnu Nair47074b82020-08-14 11:54:47 -07006998 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006999 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007000 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007001 mWindow->consumeFocusEvent(true);
7002 }
7003
Chris Ye2ad95392020-09-01 13:44:44 -07007004 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007005 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007006 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007007 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007008 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007009
7010 // Window should receive key down event.
7011 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7012 }
7013
7014 void expectKeyRepeatOnce(int32_t repeatCount) {
7015 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007016 mWindow->consumeKeyEvent(
7017 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007018 }
7019
Chris Ye2ad95392020-09-01 13:44:44 -07007020 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007021 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007022 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007023 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007024 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007025
7026 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007027 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007028 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007029 }
7030};
7031
7032TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007033 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007034 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7035 expectKeyRepeatOnce(repeatCount);
7036 }
7037}
7038
7039TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007040 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007041 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7042 expectKeyRepeatOnce(repeatCount);
7043 }
Harry Cutts33476232023-01-30 19:57:29 +00007044 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007045 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007046 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7047 expectKeyRepeatOnce(repeatCount);
7048 }
7049}
7050
7051TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007052 sendAndConsumeKeyDown(/*deviceId=*/1);
7053 expectKeyRepeatOnce(/*repeatCount=*/1);
7054 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007055 mWindow->assertNoEvents();
7056}
7057
7058TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007059 sendAndConsumeKeyDown(/*deviceId=*/1);
7060 expectKeyRepeatOnce(/*repeatCount=*/1);
7061 sendAndConsumeKeyDown(/*deviceId=*/2);
7062 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007063 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007064 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007065 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007066 expectKeyRepeatOnce(/*repeatCount=*/2);
7067 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007068 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007069 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007070 mWindow->assertNoEvents();
7071}
7072
7073TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007074 sendAndConsumeKeyDown(/*deviceId=*/1);
7075 expectKeyRepeatOnce(/*repeatCount=*/1);
7076 sendAndConsumeKeyDown(/*deviceId=*/2);
7077 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007078 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007079 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007080 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007081 mWindow->assertNoEvents();
7082}
7083
liushenxiang42232912021-05-21 20:24:09 +08007084TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7085 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007086 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007087 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007088 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7089 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7090 mWindow->assertNoEvents();
7091}
7092
Garfield Tan1c7bc862020-01-28 13:24:04 -08007093TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007094 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007095 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007096 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007097 const KeyEvent& repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007098 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007099 IdGenerator::getSource(repeatEvent.getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007100 }
7101}
7102
7103TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007104 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007105 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007106
7107 std::unordered_set<int32_t> idSet;
7108 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007109 const KeyEvent& repeatEvent = mWindow->consumeKey();
7110 int32_t id = repeatEvent.getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007111 EXPECT_EQ(idSet.end(), idSet.find(id));
7112 idSet.insert(id);
7113 }
7114}
7115
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007116/* Test InputDispatcher for MultiDisplay */
7117class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7118public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007119 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007120 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007121
Chris Yea209fde2020-07-22 13:54:51 -07007122 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007123 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007124 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007125
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007126 // Set focus window for primary display, but focused display would be second one.
7127 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007128 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007129 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7130
Vishnu Nair958da932020-08-21 17:12:37 -07007131 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007132 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007133
Chris Yea209fde2020-07-22 13:54:51 -07007134 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007135 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007136 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007137 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007138 // Set focus display to second one.
7139 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7140 // Set focus window for second display.
7141 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007142 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007143 mDispatcher->onWindowInfosChanged(
7144 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007145 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007146 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007147 }
7148
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007149 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007150 InputDispatcherTest::TearDown();
7151
Chris Yea209fde2020-07-22 13:54:51 -07007152 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007153 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007154 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007155 windowInSecondary.clear();
7156 }
7157
7158protected:
Chris Yea209fde2020-07-22 13:54:51 -07007159 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007160 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007161 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007162 sp<FakeWindowHandle> windowInSecondary;
7163};
7164
7165TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7166 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007168 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007169 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007170 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007171 windowInSecondary->assertNoEvents();
7172
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007173 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007175 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007177 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007178 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007179}
7180
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007181TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007182 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007184 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007185 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007186 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007187 windowInSecondary->assertNoEvents();
7188
7189 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007191 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007192 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007193 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007194
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007195 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007196 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007197
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007198 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007199 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007200
7201 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007202 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007203 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007204 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007205 windowInSecondary->assertNoEvents();
7206}
7207
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007208// Test per-display input monitors for motion event.
7209TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007210 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007211 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007212 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007213 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007214
7215 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007217 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007218 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007219 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007220 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007221 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007222 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007223
7224 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007226 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007227 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007228 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007229 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007230 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007231 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007232
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007233 // Lift up the touch from the second display
7234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007235 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7237 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7238 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7239
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007240 // Test inject a non-pointer motion event.
7241 // If specific a display, it will dispatch to the focused window of particular display,
7242 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007244 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007246 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007247 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007248 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007249 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007250}
7251
7252// Test per-display input monitors for key event.
7253TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007254 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007255 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007256 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007257 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007258 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007259
7260 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007262 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007263 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007264 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007265 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007266 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007267}
7268
Vishnu Nair958da932020-08-21 17:12:37 -07007269TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7270 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007271 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007272 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007273 mDispatcher->onWindowInfosChanged(
7274 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7275 *windowInSecondary->getInfo()},
7276 {},
7277 0,
7278 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007279 setFocusedWindow(secondWindowInPrimary);
7280 windowInPrimary->consumeFocusEvent(false);
7281 secondWindowInPrimary->consumeFocusEvent(true);
7282
7283 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7285 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007286 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007287 windowInPrimary->assertNoEvents();
7288 windowInSecondary->assertNoEvents();
7289 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7290}
7291
Arthur Hungdfd528e2021-12-08 13:23:04 +00007292TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7293 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007294 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007295 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007296 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007297
7298 // Test touch down on primary display.
7299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007300 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007301 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7302 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7303 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7304
7305 // Test touch down on second display.
7306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007307 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7309 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7310 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7311
7312 // Trigger cancel touch.
7313 mDispatcher->cancelCurrentTouch();
7314 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7315 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7316 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7317 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7318
7319 // Test inject a move motion event, no window/monitor should receive the event.
7320 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007321 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007322 ADISPLAY_ID_DEFAULT, {110, 200}))
7323 << "Inject motion event should return InputEventInjectionResult::FAILED";
7324 windowInPrimary->assertNoEvents();
7325 monitorInPrimary.assertNoEvents();
7326
7327 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007328 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007329 SECOND_DISPLAY_ID, {110, 200}))
7330 << "Inject motion event should return InputEventInjectionResult::FAILED";
7331 windowInSecondary->assertNoEvents();
7332 monitorInSecondary.assertNoEvents();
7333}
7334
Hu Guocb134f12023-12-23 13:42:44 +00007335/**
7336 * Send a key to the primary display and to the secondary display.
7337 * Then cause the key on the primary display to be canceled by sending in a stale key.
7338 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7339 * does not get canceled.
7340 */
7341TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7342 // Send a key down on primary display
7343 mDispatcher->notifyKey(
7344 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7345 .displayId(ADISPLAY_ID_DEFAULT)
7346 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7347 .build());
7348 windowInPrimary->consumeKeyEvent(
7349 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7350 windowInSecondary->assertNoEvents();
7351
7352 // Send a key down on second display
7353 mDispatcher->notifyKey(
7354 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7355 .displayId(SECOND_DISPLAY_ID)
7356 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7357 .build());
7358 windowInSecondary->consumeKeyEvent(
7359 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7360 windowInPrimary->assertNoEvents();
7361
7362 // Send a valid key up event on primary display that will be dropped because it is stale
7363 NotifyKeyArgs staleKeyUp =
7364 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7365 .displayId(ADISPLAY_ID_DEFAULT)
7366 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7367 .build();
7368 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7369 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7370 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7371 mDispatcher->notifyKey(staleKeyUp);
7372
7373 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7374 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7375 // receive any events.
7376 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7377 WithDisplayId(ADISPLAY_ID_DEFAULT),
7378 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7379 windowInSecondary->assertNoEvents();
7380}
7381
7382/**
7383 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7384 */
7385TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7386 // Send touch down on primary display.
7387 mDispatcher->notifyMotion(
7388 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7389 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7390 .displayId(ADISPLAY_ID_DEFAULT)
7391 .build());
7392 windowInPrimary->consumeMotionEvent(
7393 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7394 windowInSecondary->assertNoEvents();
7395
7396 // Send touch down on second display.
7397 mDispatcher->notifyMotion(
7398 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7399 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7400 .displayId(SECOND_DISPLAY_ID)
7401 .build());
7402 windowInPrimary->assertNoEvents();
7403 windowInSecondary->consumeMotionEvent(
7404 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7405
7406 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7407 NotifyMotionArgs staleMotionUp =
7408 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7409 .displayId(ADISPLAY_ID_DEFAULT)
7410 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7411 .build();
7412 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7413 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7414 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7415 mDispatcher->notifyMotion(staleMotionUp);
7416
7417 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7418 // events, where we would cancel the current keys instead.
7419 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7420 windowInSecondary->assertNoEvents();
7421}
7422
Jackal Guof9696682018-10-05 12:23:23 +08007423class InputFilterTest : public InputDispatcherTest {
7424protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007425 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7426 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007427 NotifyMotionArgs motionArgs;
7428
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007429 motionArgs =
7430 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007431 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007432 motionArgs =
7433 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007434 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007435 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007436 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007437 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007438 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007439 } else {
7440 mFakePolicy->assertFilterInputEventWasNotCalled();
7441 }
7442 }
7443
7444 void testNotifyKey(bool expectToBeFiltered) {
7445 NotifyKeyArgs keyArgs;
7446
7447 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007448 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007449 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007450 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007451 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007452
7453 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007454 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007455 } else {
7456 mFakePolicy->assertFilterInputEventWasNotCalled();
7457 }
7458 }
7459};
7460
7461// Test InputFilter for MotionEvent
7462TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7463 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007464 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7465 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007466
7467 // Enable InputFilter
7468 mDispatcher->setInputFilterEnabled(true);
7469 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007470 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7471 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007472
7473 // Disable InputFilter
7474 mDispatcher->setInputFilterEnabled(false);
7475 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007476 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7477 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007478}
7479
7480// Test InputFilter for KeyEvent
7481TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7482 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007483 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007484
7485 // Enable InputFilter
7486 mDispatcher->setInputFilterEnabled(true);
7487 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007488 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007489
7490 // Disable InputFilter
7491 mDispatcher->setInputFilterEnabled(false);
7492 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007493 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007494}
7495
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007496// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7497// logical display coordinate space.
7498TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7499 ui::Transform firstDisplayTransform;
7500 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7501 ui::Transform secondDisplayTransform;
7502 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7503
7504 std::vector<gui::DisplayInfo> displayInfos(2);
7505 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7506 displayInfos[0].transform = firstDisplayTransform;
7507 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7508 displayInfos[1].transform = secondDisplayTransform;
7509
Patrick Williamsd828f302023-04-28 17:52:08 -05007510 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007511
7512 // Enable InputFilter
7513 mDispatcher->setInputFilterEnabled(true);
7514
7515 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007516 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7517 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007518}
7519
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007520class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7521protected:
7522 virtual void SetUp() override {
7523 InputDispatcherTest::SetUp();
7524
7525 /**
7526 * We don't need to enable input filter to test the injected event policy, but we enabled it
7527 * here to make the tests more realistic, since this policy only matters when inputfilter is
7528 * on.
7529 */
7530 mDispatcher->setInputFilterEnabled(true);
7531
7532 std::shared_ptr<InputApplicationHandle> application =
7533 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007534 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7535 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007536
7537 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7538 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007539 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007540 setFocusedWindow(mWindow);
7541 mWindow->consumeFocusEvent(true);
7542 }
7543
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007544 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7545 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007546 KeyEvent event;
7547
7548 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7549 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7550 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007551 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007552 const int32_t additionalPolicyFlags =
7553 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007555 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007556 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007557 policyFlags | additionalPolicyFlags));
7558
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007559 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007560 }
7561
7562 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7563 int32_t flags) {
7564 MotionEvent event;
7565 PointerProperties pointerProperties[1];
7566 PointerCoords pointerCoords[1];
7567 pointerProperties[0].clear();
7568 pointerProperties[0].id = 0;
7569 pointerCoords[0].clear();
7570 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7571 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7572
7573 ui::Transform identityTransform;
7574 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7575 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7576 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7577 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7578 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007579 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007580 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007581 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007582
7583 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007585 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007586 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007587 policyFlags | additionalPolicyFlags));
7588
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007589 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007590 }
7591
7592private:
7593 sp<FakeWindowHandle> mWindow;
7594};
7595
7596TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007597 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7598 // filter. Without it, the event will no different from a regularly injected event, and the
7599 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007600 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7601 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007602}
7603
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007604TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007605 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007606 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007607 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7608}
7609
7610TEST_F(InputFilterInjectionPolicyTest,
7611 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7612 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007613 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007614 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007615}
7616
7617TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007618 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7619 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007620}
7621
chaviwfd6d3512019-03-25 13:23:49 -07007622class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007623 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007624 InputDispatcherTest::SetUp();
7625
Chris Yea209fde2020-07-22 13:54:51 -07007626 std::shared_ptr<FakeApplicationHandle> application =
7627 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007628 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007629 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007630 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007631
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007632 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007633 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007634 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007635
7636 // Set focused application.
7637 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007638 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007639
7640 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007641 mDispatcher->onWindowInfosChanged(
7642 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007643 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007644 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007645 }
7646
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007647 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007648 InputDispatcherTest::TearDown();
7649
7650 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007651 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007652 }
7653
7654protected:
7655 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007656 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007657 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007658};
7659
7660// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7661// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7662// the onPointerDownOutsideFocus callback.
7663TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007666 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007668 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007669
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007670 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007671 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7672}
7673
7674// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7675// DOWN on the window that doesn't have focus. Ensure no window received the
7676// onPointerDownOutsideFocus callback.
7677TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007679 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7680 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007682 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007683
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007684 ASSERT_TRUE(mDispatcher->waitForIdle());
7685 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007686}
7687
7688// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7689// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7690TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007692 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007693 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007694 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007695
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007696 ASSERT_TRUE(mDispatcher->waitForIdle());
7697 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007698}
7699
7700// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7701// DOWN on the window that already has focus. Ensure no window received the
7702// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007703TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007705 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007706 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007708 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007709
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007710 ASSERT_TRUE(mDispatcher->waitForIdle());
7711 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007712}
7713
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007714// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7715// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7716TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7717 const MotionEvent event =
7718 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7719 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007720 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007721 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7722 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007724 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7725 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7726
7727 ASSERT_TRUE(mDispatcher->waitForIdle());
7728 mFakePolicy->assertOnPointerDownWasNotCalled();
7729 // Ensure that the unfocused window did not receive any FOCUS events.
7730 mUnfocusedWindow->assertNoEvents();
7731}
7732
chaviwaf87b3e2019-10-01 16:59:28 -07007733// These tests ensures we can send touch events to a single client when there are multiple input
7734// windows that point to the same client token.
7735class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7736 virtual void SetUp() override {
7737 InputDispatcherTest::SetUp();
7738
Chris Yea209fde2020-07-22 13:54:51 -07007739 std::shared_ptr<FakeApplicationHandle> application =
7740 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007741 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7742 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007743 mWindow1->setFrame(Rect(0, 0, 100, 100));
7744
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007745 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7746 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
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,
Harry Cutts33476232023-01-30 19:57:29 +00009013 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
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);
9081 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
9082 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07009083 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9084 mWindow->setFocusable(true);
9085 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009086 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009087 }
9088};
9089
9090TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9091 // Request focus on a mirrored window
9092 setFocusedWindow(mMirror);
9093
9094 // window gets focused
9095 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009097 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009098 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9099}
9100
9101// A focused & mirrored window remains focused only if the window and its mirror are both
9102// focusable.
9103TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9104 setFocusedWindow(mMirror);
9105
9106 // window gets focused
9107 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009109 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009110 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009112 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009113 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9114
9115 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009116 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009117
9118 // window loses focus since one of the windows associated with the token in not focusable
9119 mWindow->consumeFocusEvent(false);
9120
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009121 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009122 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009123 mWindow->assertNoEvents();
9124}
9125
9126// A focused & mirrored window remains focused until the window and its mirror both become
9127// invisible.
9128TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9129 setFocusedWindow(mMirror);
9130
9131 // window gets focused
9132 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009134 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009135 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009137 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009138 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9139
9140 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009141 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009142
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009144 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009145 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009147 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009148 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9149
9150 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009151 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009152
9153 // window loses focus only after all windows associated with the token become invisible.
9154 mWindow->consumeFocusEvent(false);
9155
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009156 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009157 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009158 mWindow->assertNoEvents();
9159}
9160
9161// A focused & mirrored window remains focused until both windows are removed.
9162TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9163 setFocusedWindow(mMirror);
9164
9165 // window gets focused
9166 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009168 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009169 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009171 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009172 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9173
9174 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009175 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009176
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009178 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009179 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009181 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009182 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9183
9184 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009185 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009186 mWindow->consumeFocusEvent(false);
9187
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009188 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009189 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009190 mWindow->assertNoEvents();
9191}
9192
9193// Focus request can be pending until one window becomes visible.
9194TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9195 // Request focus on an invisible mirror.
9196 mWindow->setVisible(false);
9197 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009198 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009199 setFocusedWindow(mMirror);
9200
9201 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009203 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9204 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009205
9206 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009207 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009208
9209 // window gets focused
9210 mWindow->consumeFocusEvent(true);
9211 // window gets the pending key event
9212 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9213}
Prabir Pradhan99987712020-11-10 18:43:05 -08009214
9215class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9216protected:
9217 std::shared_ptr<FakeApplicationHandle> mApp;
9218 sp<FakeWindowHandle> mWindow;
9219 sp<FakeWindowHandle> mSecondWindow;
9220
9221 void SetUp() override {
9222 InputDispatcherTest::SetUp();
9223 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009224 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009225 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009226 mSecondWindow =
9227 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009228 mSecondWindow->setFocusable(true);
9229
9230 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009231 mDispatcher->onWindowInfosChanged(
9232 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009233
9234 setFocusedWindow(mWindow);
9235 mWindow->consumeFocusEvent(true);
9236 }
9237
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009238 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009239 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009240 }
9241
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009242 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9243 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009244 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009245 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9246 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009247 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009248 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009249 }
9250};
9251
9252TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9253 // Ensure that capture cannot be obtained for unfocused windows.
9254 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9255 mFakePolicy->assertSetPointerCaptureNotCalled();
9256 mSecondWindow->assertNoEvents();
9257
9258 // Ensure that capture can be enabled from the focus window.
9259 requestAndVerifyPointerCapture(mWindow, true);
9260
9261 // Ensure that capture cannot be disabled from a window that does not have capture.
9262 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9263 mFakePolicy->assertSetPointerCaptureNotCalled();
9264
9265 // Ensure that capture can be disabled from the window with capture.
9266 requestAndVerifyPointerCapture(mWindow, false);
9267}
9268
9269TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009270 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009271
9272 setFocusedWindow(mSecondWindow);
9273
9274 // Ensure that the capture disabled event was sent first.
9275 mWindow->consumeCaptureEvent(false);
9276 mWindow->consumeFocusEvent(false);
9277 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009278 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009279
9280 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009281 notifyPointerCaptureChanged({});
9282 notifyPointerCaptureChanged(request);
9283 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009284 mWindow->assertNoEvents();
9285 mSecondWindow->assertNoEvents();
9286 mFakePolicy->assertSetPointerCaptureNotCalled();
9287}
9288
9289TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009290 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009291
9292 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009293 notifyPointerCaptureChanged({});
9294 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009295
9296 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009297 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009298 mWindow->consumeCaptureEvent(false);
9299 mWindow->assertNoEvents();
9300}
9301
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009302TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9303 requestAndVerifyPointerCapture(mWindow, true);
9304
9305 // The first window loses focus.
9306 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009307 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009308 mWindow->consumeCaptureEvent(false);
9309
9310 // Request Pointer Capture from the second window before the notification from InputReader
9311 // arrives.
9312 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009313 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009314
9315 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009316 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009317
9318 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009319 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009320
9321 mSecondWindow->consumeFocusEvent(true);
9322 mSecondWindow->consumeCaptureEvent(true);
9323}
9324
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009325TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9326 // App repeatedly enables and disables capture.
9327 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9328 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9329 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9330 mFakePolicy->assertSetPointerCaptureCalled(false);
9331 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9332 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9333
9334 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9335 // first request is now stale, this should do nothing.
9336 notifyPointerCaptureChanged(firstRequest);
9337 mWindow->assertNoEvents();
9338
9339 // InputReader notifies that the second request was enabled.
9340 notifyPointerCaptureChanged(secondRequest);
9341 mWindow->consumeCaptureEvent(true);
9342}
9343
Prabir Pradhan7092e262022-05-03 16:51:09 +00009344TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9345 requestAndVerifyPointerCapture(mWindow, true);
9346
9347 // App toggles pointer capture off and on.
9348 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9349 mFakePolicy->assertSetPointerCaptureCalled(false);
9350
9351 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9352 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9353
9354 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9355 // preceding "disable" request.
9356 notifyPointerCaptureChanged(enableRequest);
9357
9358 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9359 // any notifications.
9360 mWindow->assertNoEvents();
9361}
9362
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009363/**
9364 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9365 * mouse movements don't affect the previous mouse hovering state.
9366 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9367 * HOVER_MOVE events).
9368 */
9369TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9370 // Mouse hover on the window
9371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9372 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9373 .build());
9374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9375 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9376 .build());
9377
9378 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9379 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9380
9381 // Start pointer capture
9382 requestAndVerifyPointerCapture(mWindow, true);
9383
9384 // Send some relative mouse movements and receive them in the window.
9385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9386 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9387 .build());
9388 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9389 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9390
9391 // Stop pointer capture
9392 requestAndVerifyPointerCapture(mWindow, false);
9393
9394 // Continue hovering on the window
9395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9396 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9397 .build());
9398 mWindow->consumeMotionEvent(
9399 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9400
9401 mWindow->assertNoEvents();
9402}
9403
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009404class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9405protected:
9406 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009407
9408 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9409 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9410
9411 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9412 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9413
9414 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9415 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9416 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9417 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9418 MAXIMUM_OBSCURING_OPACITY);
9419
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009420 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9421 static constexpr gui::Uid APP_B_UID{10002};
9422 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009423
9424 sp<FakeWindowHandle> mTouchWindow;
9425
9426 virtual void SetUp() override {
9427 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009428 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009429 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9430 }
9431
9432 virtual void TearDown() override {
9433 InputDispatcherTest::TearDown();
9434 mTouchWindow.clear();
9435 }
9436
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009437 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009438 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009439 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009440 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009441 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009442 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009443 return window;
9444 }
9445
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009446 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009447 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9448 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009449 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009450 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009451 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009452 return window;
9453 }
9454
9455 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009456 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9457 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9458 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009459 }
9460};
9461
9462TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009463 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009464 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009465 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009466
9467 touch();
9468
9469 mTouchWindow->assertNoEvents();
9470}
9471
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009472TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009473 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9474 const sp<FakeWindowHandle>& w =
9475 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009476 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009477
9478 touch();
9479
9480 mTouchWindow->assertNoEvents();
9481}
9482
9483TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009484 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9485 const sp<FakeWindowHandle>& w =
9486 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009487 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009488
9489 touch();
9490
9491 w->assertNoEvents();
9492}
9493
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009494TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009495 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009496 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009497
9498 touch();
9499
9500 mTouchWindow->consumeAnyMotionDown();
9501}
9502
9503TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009504 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009505 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009506 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009507 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009508
9509 touch({PointF{100, 100}});
9510
9511 mTouchWindow->consumeAnyMotionDown();
9512}
9513
9514TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009515 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009516 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009517 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009518
9519 touch();
9520
9521 mTouchWindow->consumeAnyMotionDown();
9522}
9523
9524TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9525 const sp<FakeWindowHandle>& w =
9526 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009527 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009528
9529 touch();
9530
9531 mTouchWindow->consumeAnyMotionDown();
9532}
9533
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009534TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9535 const sp<FakeWindowHandle>& w =
9536 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009537 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009538
9539 touch();
9540
9541 w->assertNoEvents();
9542}
9543
9544/**
9545 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9546 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9547 * window, the occluding window will still receive ACTION_OUTSIDE event.
9548 */
9549TEST_F(InputDispatcherUntrustedTouchesTest,
9550 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9551 const sp<FakeWindowHandle>& w =
9552 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009553 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009554 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009555
9556 touch();
9557
9558 w->consumeMotionOutside();
9559}
9560
9561TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9562 const sp<FakeWindowHandle>& w =
9563 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009564 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009565 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009566
9567 touch();
9568
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009569 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009570}
9571
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009572TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009573 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009574 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9575 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009576 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009577
9578 touch();
9579
9580 mTouchWindow->consumeAnyMotionDown();
9581}
9582
9583TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9584 const sp<FakeWindowHandle>& w =
9585 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9586 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009587 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009588
9589 touch();
9590
9591 mTouchWindow->consumeAnyMotionDown();
9592}
9593
9594TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009595 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009596 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9597 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009598 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009599
9600 touch();
9601
9602 mTouchWindow->assertNoEvents();
9603}
9604
9605TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9606 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9607 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009608 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9609 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009610 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009611 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9612 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009613 mDispatcher->onWindowInfosChanged(
9614 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009615
9616 touch();
9617
9618 mTouchWindow->assertNoEvents();
9619}
9620
9621TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9622 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9623 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009624 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9625 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009626 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009627 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9628 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009629 mDispatcher->onWindowInfosChanged(
9630 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009631
9632 touch();
9633
9634 mTouchWindow->consumeAnyMotionDown();
9635}
9636
9637TEST_F(InputDispatcherUntrustedTouchesTest,
9638 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9639 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009640 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9641 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009642 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009643 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9644 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009645 mDispatcher->onWindowInfosChanged(
9646 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009647
9648 touch();
9649
9650 mTouchWindow->consumeAnyMotionDown();
9651}
9652
9653TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9654 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009655 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9656 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009657 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009658 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9659 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009660 mDispatcher->onWindowInfosChanged(
9661 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009662
9663 touch();
9664
9665 mTouchWindow->assertNoEvents();
9666}
9667
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009668TEST_F(InputDispatcherUntrustedTouchesTest,
9669 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9670 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009671 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9672 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009673 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009674 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9675 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009676 mDispatcher->onWindowInfosChanged(
9677 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009678
9679 touch();
9680
9681 mTouchWindow->assertNoEvents();
9682}
9683
9684TEST_F(InputDispatcherUntrustedTouchesTest,
9685 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9686 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009687 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9688 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009689 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009690 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9691 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009692 mDispatcher->onWindowInfosChanged(
9693 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009694
9695 touch();
9696
9697 mTouchWindow->consumeAnyMotionDown();
9698}
9699
9700TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9701 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009702 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9703 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009704 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009705
9706 touch();
9707
9708 mTouchWindow->consumeAnyMotionDown();
9709}
9710
9711TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9712 const sp<FakeWindowHandle>& w =
9713 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009714 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009715
9716 touch();
9717
9718 mTouchWindow->consumeAnyMotionDown();
9719}
9720
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009721TEST_F(InputDispatcherUntrustedTouchesTest,
9722 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9723 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9724 const sp<FakeWindowHandle>& w =
9725 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009726 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009727
9728 touch();
9729
9730 mTouchWindow->assertNoEvents();
9731}
9732
9733TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9734 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9735 const sp<FakeWindowHandle>& w =
9736 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009737 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009738
9739 touch();
9740
9741 mTouchWindow->consumeAnyMotionDown();
9742}
9743
9744TEST_F(InputDispatcherUntrustedTouchesTest,
9745 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9746 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9747 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009748 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9749 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009750 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009751
9752 touch();
9753
9754 mTouchWindow->consumeAnyMotionDown();
9755}
9756
9757TEST_F(InputDispatcherUntrustedTouchesTest,
9758 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9759 const sp<FakeWindowHandle>& w1 =
9760 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9761 OPACITY_BELOW_THRESHOLD);
9762 const sp<FakeWindowHandle>& w2 =
9763 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9764 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009765 mDispatcher->onWindowInfosChanged(
9766 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009767
9768 touch();
9769
9770 mTouchWindow->assertNoEvents();
9771}
9772
9773/**
9774 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9775 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9776 * (which alone would result in allowing touches) does not affect the blocking behavior.
9777 */
9778TEST_F(InputDispatcherUntrustedTouchesTest,
9779 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9780 const sp<FakeWindowHandle>& wB =
9781 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9782 OPACITY_BELOW_THRESHOLD);
9783 const sp<FakeWindowHandle>& wC =
9784 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9785 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009786 mDispatcher->onWindowInfosChanged(
9787 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009788
9789 touch();
9790
9791 mTouchWindow->assertNoEvents();
9792}
9793
9794/**
9795 * This test is testing that a window from a different UID but with same application token doesn't
9796 * block the touch. Apps can share the application token for close UI collaboration for example.
9797 */
9798TEST_F(InputDispatcherUntrustedTouchesTest,
9799 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9800 const sp<FakeWindowHandle>& w =
9801 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9802 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009803 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009804
9805 touch();
9806
9807 mTouchWindow->consumeAnyMotionDown();
9808}
9809
arthurhungb89ccb02020-12-30 16:19:01 +08009810class InputDispatcherDragTests : public InputDispatcherTest {
9811protected:
9812 std::shared_ptr<FakeApplicationHandle> mApp;
9813 sp<FakeWindowHandle> mWindow;
9814 sp<FakeWindowHandle> mSecondWindow;
9815 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009816 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009817 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9818 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009819
9820 void SetUp() override {
9821 InputDispatcherTest::SetUp();
9822 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009823 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009824 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009825
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009826 mSecondWindow =
9827 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009828 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009829
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009830 mSpyWindow =
9831 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009832 mSpyWindow->setSpy(true);
9833 mSpyWindow->setTrustedOverlay(true);
9834 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9835
arthurhungb89ccb02020-12-30 16:19:01 +08009836 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009837 mDispatcher->onWindowInfosChanged(
9838 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9839 {},
9840 0,
9841 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009842 }
9843
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009844 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9845 switch (fromSource) {
9846 case AINPUT_SOURCE_TOUCHSCREEN:
9847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009848 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009849 ADISPLAY_ID_DEFAULT, {50, 50}))
9850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9851 break;
9852 case AINPUT_SOURCE_STYLUS:
9853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009854 injectMotionEvent(*mDispatcher,
9855 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9856 AINPUT_SOURCE_STYLUS)
9857 .buttonState(
9858 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9859 .pointer(PointerBuilder(0, ToolType::STYLUS)
9860 .x(50)
9861 .y(50))
9862 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009863 break;
9864 case AINPUT_SOURCE_MOUSE:
9865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009866 injectMotionEvent(*mDispatcher,
9867 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9868 AINPUT_SOURCE_MOUSE)
9869 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9870 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9871 ToolType::MOUSE)
9872 .x(50)
9873 .y(50))
9874 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009875 break;
9876 default:
9877 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9878 }
arthurhungb89ccb02020-12-30 16:19:01 +08009879
9880 // Window should receive motion event.
9881 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009882 // Spy window should also receive motion event
9883 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009884 }
9885
9886 // Start performing drag, we will create a drag window and transfer touch to it.
9887 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9888 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009889 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009890 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009891 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009892 }
arthurhungb89ccb02020-12-30 16:19:01 +08009893
9894 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009895 mDragWindow =
9896 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009897 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009898 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9899 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9900 {},
9901 0,
9902 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009903
9904 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009905 bool transferred =
9906 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009907 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009908 if (transferred) {
9909 mWindow->consumeMotionCancel();
9910 mDragWindow->consumeMotionDown();
9911 }
9912 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009913 }
9914};
9915
9916TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009917 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009918
9919 // Move on window.
9920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009921 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009922 ADISPLAY_ID_DEFAULT, {50, 50}))
9923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9924 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9925 mWindow->consumeDragEvent(false, 50, 50);
9926 mSecondWindow->assertNoEvents();
9927
9928 // Move to another window.
9929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009930 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009931 ADISPLAY_ID_DEFAULT, {150, 50}))
9932 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9933 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9934 mWindow->consumeDragEvent(true, 150, 50);
9935 mSecondWindow->consumeDragEvent(false, 50, 50);
9936
9937 // Move back to original window.
9938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009939 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009940 ADISPLAY_ID_DEFAULT, {50, 50}))
9941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9942 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9943 mWindow->consumeDragEvent(false, 50, 50);
9944 mSecondWindow->consumeDragEvent(true, -50, 50);
9945
9946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009947 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9948 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9950 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9951 mWindow->assertNoEvents();
9952 mSecondWindow->assertNoEvents();
9953}
9954
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009955TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009956 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009957
9958 // No cancel event after drag start
9959 mSpyWindow->assertNoEvents();
9960
9961 const MotionEvent secondFingerDownEvent =
9962 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9963 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009964 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9965 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009966 .build();
9967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009968 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009969 InputEventInjectionSync::WAIT_FOR_RESULT))
9970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9971
9972 // Receives cancel for first pointer after next pointer down
9973 mSpyWindow->consumeMotionCancel();
9974 mSpyWindow->consumeMotionDown();
9975
9976 mSpyWindow->assertNoEvents();
9977}
9978
arthurhungf452d0b2021-01-06 00:19:52 +08009979TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009980 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009981
9982 // Move on window.
9983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009984 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009985 ADISPLAY_ID_DEFAULT, {50, 50}))
9986 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9987 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9988 mWindow->consumeDragEvent(false, 50, 50);
9989 mSecondWindow->assertNoEvents();
9990
9991 // Move to another window.
9992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009993 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009994 ADISPLAY_ID_DEFAULT, {150, 50}))
9995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9996 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9997 mWindow->consumeDragEvent(true, 150, 50);
9998 mSecondWindow->consumeDragEvent(false, 50, 50);
9999
10000 // drop to another window.
10001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010002 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010003 {150, 50}))
10004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10005 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010006 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010007 mWindow->assertNoEvents();
10008 mSecondWindow->assertNoEvents();
10009}
10010
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010011TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10012 startDrag();
10013
10014 // No cancel event after drag start
10015 mSpyWindow->assertNoEvents();
10016
10017 const MotionEvent secondFingerDownEvent =
10018 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10019 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10020 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10021 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10022 .build();
10023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10024 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10025 InputEventInjectionSync::WAIT_FOR_RESULT))
10026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10027
10028 // Receives cancel for first pointer after next pointer down
10029 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010030 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010031 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10032
10033 mSpyWindow->assertNoEvents();
10034
10035 // Spy window calls pilfer pointers
10036 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10037 mDragWindow->assertNoEvents();
10038
10039 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010040 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010041 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10042 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10043 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10044 .build();
10045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010046 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010047 InputEventInjectionSync::WAIT_FOR_RESULT))
10048 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10049
10050 // Drag window should still receive the new event
10051 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10052 mDragWindow->assertNoEvents();
10053}
10054
arthurhung6d4bed92021-03-17 11:59:33 +080010055TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010056 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010057
10058 // Move on window and keep button pressed.
10059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010060 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010061 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10062 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010063 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010064 .build()))
10065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10066 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10067 mWindow->consumeDragEvent(false, 50, 50);
10068 mSecondWindow->assertNoEvents();
10069
10070 // Move to another window and release button, expect to drop item.
10071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010072 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010073 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10074 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010075 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010076 .build()))
10077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10078 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10079 mWindow->assertNoEvents();
10080 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010081 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010082
10083 // nothing to the window.
10084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010085 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010086 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10087 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010088 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010089 .build()))
10090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10091 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10092 mWindow->assertNoEvents();
10093 mSecondWindow->assertNoEvents();
10094}
10095
Arthur Hung54745652022-04-20 07:17:41 +000010096TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010097 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010098
10099 // Set second window invisible.
10100 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010101 mDispatcher->onWindowInfosChanged(
10102 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010103
10104 // Move on window.
10105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010106 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010107 ADISPLAY_ID_DEFAULT, {50, 50}))
10108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10109 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10110 mWindow->consumeDragEvent(false, 50, 50);
10111 mSecondWindow->assertNoEvents();
10112
10113 // Move to another window.
10114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010115 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010116 ADISPLAY_ID_DEFAULT, {150, 50}))
10117 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10118 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10119 mWindow->consumeDragEvent(true, 150, 50);
10120 mSecondWindow->assertNoEvents();
10121
10122 // drop to another window.
10123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010124 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010125 {150, 50}))
10126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10127 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010128 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010129 mWindow->assertNoEvents();
10130 mSecondWindow->assertNoEvents();
10131}
10132
Arthur Hung54745652022-04-20 07:17:41 +000010133TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010134 // Ensure window could track pointerIds if it didn't support split touch.
10135 mWindow->setPreventSplitting(true);
10136
Arthur Hung54745652022-04-20 07:17:41 +000010137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010138 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010139 {50, 50}))
10140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10141 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10142
10143 const MotionEvent secondFingerDownEvent =
10144 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10145 .displayId(ADISPLAY_ID_DEFAULT)
10146 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010147 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10148 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010149 .build();
10150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010151 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010152 InputEventInjectionSync::WAIT_FOR_RESULT))
10153 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010154 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010155
10156 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010157 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010158}
10159
10160TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10161 // First down on second window.
10162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010163 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010164 {150, 50}))
10165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10166
10167 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10168
10169 // Second down on first window.
10170 const MotionEvent secondFingerDownEvent =
10171 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10172 .displayId(ADISPLAY_ID_DEFAULT)
10173 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010174 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10175 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010176 .build();
10177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010178 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010179 InputEventInjectionSync::WAIT_FOR_RESULT))
10180 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10181 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10182
10183 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010184 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010185
10186 // Move on window.
10187 const MotionEvent secondFingerMoveEvent =
10188 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10189 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010190 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10191 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010192 .build();
10193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010194 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010195 InputEventInjectionSync::WAIT_FOR_RESULT));
10196 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10197 mWindow->consumeDragEvent(false, 50, 50);
10198 mSecondWindow->consumeMotionMove();
10199
10200 // Release the drag pointer should perform drop.
10201 const MotionEvent secondFingerUpEvent =
10202 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10203 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010204 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10205 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010206 .build();
10207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010208 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010209 InputEventInjectionSync::WAIT_FOR_RESULT));
10210 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010211 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010212 mWindow->assertNoEvents();
10213 mSecondWindow->consumeMotionMove();
10214}
10215
Arthur Hung3915c1f2022-05-31 07:17:17 +000010216TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010217 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010218
10219 // Update window of second display.
10220 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010221 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010222 mDispatcher->onWindowInfosChanged(
10223 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10224 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10225 {},
10226 0,
10227 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010228
10229 // Let second display has a touch state.
10230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010231 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010232 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10233 AINPUT_SOURCE_TOUCHSCREEN)
10234 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010235 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010236 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010237 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010238 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010239 mDispatcher->onWindowInfosChanged(
10240 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10241 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10242 {},
10243 0,
10244 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010245
10246 // Move on window.
10247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010248 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010249 ADISPLAY_ID_DEFAULT, {50, 50}))
10250 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10251 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10252 mWindow->consumeDragEvent(false, 50, 50);
10253 mSecondWindow->assertNoEvents();
10254
10255 // Move to another window.
10256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010257 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010258 ADISPLAY_ID_DEFAULT, {150, 50}))
10259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10260 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10261 mWindow->consumeDragEvent(true, 150, 50);
10262 mSecondWindow->consumeDragEvent(false, 50, 50);
10263
10264 // drop to another window.
10265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010266 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010267 {150, 50}))
10268 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10269 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010270 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010271 mWindow->assertNoEvents();
10272 mSecondWindow->assertNoEvents();
10273}
10274
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010275TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10276 startDrag(true, AINPUT_SOURCE_MOUSE);
10277 // Move on window.
10278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010279 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010280 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10281 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010282 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010283 .x(50)
10284 .y(50))
10285 .build()))
10286 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10287 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10288 mWindow->consumeDragEvent(false, 50, 50);
10289 mSecondWindow->assertNoEvents();
10290
10291 // Move to another window.
10292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010293 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010294 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10295 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010296 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010297 .x(150)
10298 .y(50))
10299 .build()))
10300 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10301 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10302 mWindow->consumeDragEvent(true, 150, 50);
10303 mSecondWindow->consumeDragEvent(false, 50, 50);
10304
10305 // drop to another window.
10306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010307 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010308 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10309 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010310 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010311 .x(150)
10312 .y(50))
10313 .build()))
10314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10315 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010316 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010317 mWindow->assertNoEvents();
10318 mSecondWindow->assertNoEvents();
10319}
10320
Linnan Li5af92f92023-07-14 14:36:22 +080010321/**
10322 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10323 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10324 */
10325TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10326 // Down on second window
10327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10328 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10329 {150, 50}))
10330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10331
10332 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10333 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10334
10335 // Down on first window
10336 const MotionEvent secondFingerDownEvent =
10337 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10338 .displayId(ADISPLAY_ID_DEFAULT)
10339 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10340 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10341 .build();
10342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10343 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10344 InputEventInjectionSync::WAIT_FOR_RESULT))
10345 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10346 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10347 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10348 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10349
10350 // Start drag on first window
10351 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10352
10353 // Trigger cancel
10354 mDispatcher->cancelCurrentTouch();
10355 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10356 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10357 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10358
10359 ASSERT_TRUE(mDispatcher->waitForIdle());
10360 // The D&D finished with nullptr
10361 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10362
10363 // Remove drag window
10364 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10365
10366 // Inject a simple gesture, ensure dispatcher not crashed
10367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10368 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10369 PointF{50, 50}))
10370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10371 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10372
10373 const MotionEvent moveEvent =
10374 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10375 .displayId(ADISPLAY_ID_DEFAULT)
10376 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10377 .build();
10378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10379 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10380 InputEventInjectionSync::WAIT_FOR_RESULT))
10381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10382 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10383
10384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10385 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10386 {50, 50}))
10387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10388 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10389}
10390
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010391TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10392 // Start hovering over the window.
10393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10394 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10395 ADISPLAY_ID_DEFAULT, {50, 50}));
10396
10397 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10398 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10399
10400 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10401 << "Drag and drop should not work with a hovering pointer";
10402}
10403
Vishnu Nair062a8672021-09-03 16:07:44 -070010404class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10405
10406TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10407 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010408 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10409 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010410 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010411 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10412 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010413 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010414 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010415 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010416
10417 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010418 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010419 window->assertNoEvents();
10420
Prabir Pradhan678438e2023-04-13 19:32:51 +000010421 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10422 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010423 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10424 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010425 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010426 window->assertNoEvents();
10427
10428 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010429 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010430 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010431
Prabir Pradhan678438e2023-04-13 19:32:51 +000010432 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010433 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10434
Prabir Pradhan678438e2023-04-13 19:32:51 +000010435 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10436 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010437 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10438 window->assertNoEvents();
10439}
10440
10441TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10442 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10443 std::make_shared<FakeApplicationHandle>();
10444 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010445 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10446 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010447 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010448 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010449 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010451 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10452 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010453 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010454 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010455 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10456 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010457 mDispatcher->onWindowInfosChanged(
10458 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010459 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010460 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010461
10462 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010463 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010464 window->assertNoEvents();
10465
Prabir Pradhan678438e2023-04-13 19:32:51 +000010466 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10467 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010468 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10469 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010470 window->assertNoEvents();
10471
10472 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010473 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010474 mDispatcher->onWindowInfosChanged(
10475 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010476
Prabir Pradhan678438e2023-04-13 19:32:51 +000010477 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010478 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10479
Prabir Pradhan678438e2023-04-13 19:32:51 +000010480 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10481 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010482 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10483 window->assertNoEvents();
10484}
10485
10486TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10487 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10488 std::make_shared<FakeApplicationHandle>();
10489 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010490 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10491 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010492 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010493 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010494 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010495 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010496 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10497 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010498 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010499 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010500 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10501 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010502 mDispatcher->onWindowInfosChanged(
10503 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010504 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010505 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010506
10507 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010508 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010509 window->assertNoEvents();
10510
Prabir Pradhan678438e2023-04-13 19:32:51 +000010511 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10512 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010513 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10514 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010515 window->assertNoEvents();
10516
10517 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010518 mDispatcher->onWindowInfosChanged(
10519 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010520
Prabir Pradhan678438e2023-04-13 19:32:51 +000010521 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010522 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10523
Prabir Pradhan678438e2023-04-13 19:32:51 +000010524 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10525 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010526 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10527 window->assertNoEvents();
10528}
10529
Antonio Kantekf16f2832021-09-28 04:39:20 +000010530class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10531protected:
10532 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010533 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010534 sp<FakeWindowHandle> mWindow;
10535 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010536 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010537
10538 void SetUp() override {
10539 InputDispatcherTest::SetUp();
10540
10541 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010542 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010543 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010544 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010545 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010546 mSecondWindow =
10547 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010548 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010549 mThirdWindow =
10550 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10551 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10552 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010553
10554 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010555 mDispatcher->onWindowInfosChanged(
10556 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10557 {},
10558 0,
10559 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010560 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010561 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010562
Antonio Kantek15beb512022-06-13 22:35:41 +000010563 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010564 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010565 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010566 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10567 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010568 mThirdWindow->assertNoEvents();
10569 }
10570
10571 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10572 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010573 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010574 SECOND_DISPLAY_ID)) {
10575 mWindow->assertNoEvents();
10576 mSecondWindow->assertNoEvents();
10577 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010578 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010579 }
10580
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010581 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010582 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010583 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10584 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010585 mWindow->consumeTouchModeEvent(inTouchMode);
10586 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010587 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010588 }
10589};
10590
Antonio Kantek26defcf2022-02-08 01:12:27 +000010591TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010592 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010593 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10594 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010595 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010596}
10597
Antonio Kantek26defcf2022-02-08 01:12:27 +000010598TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10599 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010600 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010601 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010602 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010603 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010604 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010605 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010606 mWindow->assertNoEvents();
10607 mSecondWindow->assertNoEvents();
10608}
10609
10610TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10611 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010612 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010613 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010614 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010615 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010616 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010617}
10618
Antonio Kantekf16f2832021-09-28 04:39:20 +000010619TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010620 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010621 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10622 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010623 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010624 mWindow->assertNoEvents();
10625 mSecondWindow->assertNoEvents();
10626}
10627
Antonio Kantek15beb512022-06-13 22:35:41 +000010628TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10629 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10630 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10631 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010632 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010633 mWindow->assertNoEvents();
10634 mSecondWindow->assertNoEvents();
10635 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10636}
10637
Antonio Kantek48710e42022-03-24 14:19:30 -070010638TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10639 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10641 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10643 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10644
10645 // Then remove focus.
10646 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010647 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010648
10649 // Assert that caller can switch touch mode by owning one of the last interacted window.
10650 const WindowInfo& windowInfo = *mWindow->getInfo();
10651 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10652 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010653 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010654}
10655
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010656class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10657public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010658 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010659 std::shared_ptr<FakeApplicationHandle> application =
10660 std::make_shared<FakeApplicationHandle>();
10661 std::string name = "Fake Spy ";
10662 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010663 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10664 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010665 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010666 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010667 return spy;
10668 }
10669
10670 sp<FakeWindowHandle> createForeground() {
10671 std::shared_ptr<FakeApplicationHandle> application =
10672 std::make_shared<FakeApplicationHandle>();
10673 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010674 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10675 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010676 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010677 return window;
10678 }
10679
10680private:
10681 int mSpyCount{0};
10682};
10683
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010684using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010685/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010686 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10687 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010688TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010689 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010690 ScopedSilentDeath _silentDeath;
10691
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010692 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010693 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010694 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010695 ".* not a trusted overlay");
10696}
10697
10698/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010699 * Input injection into a display with a spy window but no foreground windows should succeed.
10700 */
10701TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010702 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010703 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010704
10705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010706 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10708 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10709}
10710
10711/**
10712 * Verify the order in which different input windows receive events. The touched foreground window
10713 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10714 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10715 * receive events before ones belows it.
10716 *
10717 * Here, we set up a scenario with four windows in the following Z order from the top:
10718 * spy1, spy2, window, spy3.
10719 * We then inject an event and verify that the foreground "window" receives it first, followed by
10720 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10721 * window.
10722 */
10723TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10724 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010725 auto spy1 = createSpy();
10726 auto spy2 = createSpy();
10727 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010728 mDispatcher->onWindowInfosChanged(
10729 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010730 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10731 const size_t numChannels = channels.size();
10732
Michael Wright8e9a8562022-02-09 13:44:29 +000010733 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010734 if (!epollFd.ok()) {
10735 FAIL() << "Failed to create epoll fd";
10736 }
10737
10738 for (size_t i = 0; i < numChannels; i++) {
10739 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10740 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10741 FAIL() << "Failed to add fd to epoll";
10742 }
10743 }
10744
10745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10748
10749 std::vector<size_t> eventOrder;
10750 std::vector<struct epoll_event> events(numChannels);
10751 for (;;) {
10752 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10753 (100ms).count());
10754 if (nFds < 0) {
10755 FAIL() << "Failed to call epoll_wait";
10756 }
10757 if (nFds == 0) {
10758 break; // epoll_wait timed out
10759 }
10760 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010761 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010762 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010763 channels[i]->consumeMotionDown();
10764 }
10765 }
10766
10767 // Verify the order in which the events were received.
10768 EXPECT_EQ(3u, eventOrder.size());
10769 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10770 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10771 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10772}
10773
10774/**
10775 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10776 */
10777TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10778 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010779 auto spy = createSpy();
10780 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010781 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010782
10783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010784 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010785 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10786 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10787 spy->assertNoEvents();
10788}
10789
10790/**
10791 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10792 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10793 * to the window.
10794 */
10795TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10796 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010797 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010798 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010799 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010800
10801 // Inject an event outside the spy window's touchable region.
10802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10805 window->consumeMotionDown();
10806 spy->assertNoEvents();
10807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010808 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10810 window->consumeMotionUp();
10811 spy->assertNoEvents();
10812
10813 // Inject an event inside the spy window's touchable region.
10814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010815 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010816 {5, 10}))
10817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10818 window->consumeMotionDown();
10819 spy->consumeMotionDown();
10820}
10821
10822/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010823 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010824 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010825 */
10826TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10827 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010828 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010829 auto spy = createSpy();
10830 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010831 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010832 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010833 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010834
10835 // Inject an event outside the spy window's frame and touchable region.
10836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010838 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10840 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010841 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010842}
10843
10844/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010845 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10846 * pointers that are down within its bounds.
10847 */
10848TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10849 auto windowLeft = createForeground();
10850 windowLeft->setFrame({0, 0, 100, 200});
10851 auto windowRight = createForeground();
10852 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010853 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010854 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010855 mDispatcher->onWindowInfosChanged(
10856 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010857
10858 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010859 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010860 {50, 50}))
10861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10862 windowLeft->consumeMotionDown();
10863 spy->consumeMotionDown();
10864
10865 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010866 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010867 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010868 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10869 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010870 .build();
10871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010872 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010873 InputEventInjectionSync::WAIT_FOR_RESULT))
10874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10875 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010876 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010877}
10878
10879/**
10880 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10881 * the spy should receive the second pointer with ACTION_DOWN.
10882 */
10883TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10884 auto window = createForeground();
10885 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010886 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010887 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010888 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010889
10890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010891 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010892 {50, 50}))
10893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10894 window->consumeMotionDown();
10895 spyRight->assertNoEvents();
10896
10897 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010898 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010899 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010900 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10901 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010902 .build();
10903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010904 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010905 InputEventInjectionSync::WAIT_FOR_RESULT))
10906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010907 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010908 spyRight->consumeMotionDown();
10909}
10910
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010911/**
10912 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10913 * windows should be allowed to control split touch.
10914 */
10915TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010916 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010917 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010918 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010919 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010920
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010921 auto window = createForeground();
10922 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010923
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010924 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010925
10926 // First finger down, no window touched.
10927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010928 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010929 {100, 200}))
10930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10931 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10932 window->assertNoEvents();
10933
10934 // Second finger down on window, the window should receive touch down.
10935 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010936 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010937 .displayId(ADISPLAY_ID_DEFAULT)
10938 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010939 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010941 .build();
10942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010943 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010944 InputEventInjectionSync::WAIT_FOR_RESULT))
10945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10946
10947 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010948 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010949}
10950
10951/**
10952 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10953 * do not receive key events.
10954 */
10955TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010956 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010957 spy->setFocusable(false);
10958
10959 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010960 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010961 setFocusedWindow(window);
10962 window->consumeFocusEvent(true);
10963
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010965 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10966 window->consumeKeyDown(ADISPLAY_ID_NONE);
10967
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010969 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10970 window->consumeKeyUp(ADISPLAY_ID_NONE);
10971
10972 spy->assertNoEvents();
10973}
10974
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010975using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10976
10977/**
10978 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10979 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10980 */
10981TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10982 auto window = createForeground();
10983 auto spy1 = createSpy();
10984 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010985 mDispatcher->onWindowInfosChanged(
10986 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010987
10988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010989 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10991 window->consumeMotionDown();
10992 spy1->consumeMotionDown();
10993 spy2->consumeMotionDown();
10994
10995 // Pilfer pointers from the second spy window.
10996 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10997 spy2->assertNoEvents();
10998 spy1->consumeMotionCancel();
10999 window->consumeMotionCancel();
11000
11001 // The rest of the gesture should only be sent to the second spy window.
11002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011003 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011004 ADISPLAY_ID_DEFAULT))
11005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11006 spy2->consumeMotionMove();
11007 spy1->assertNoEvents();
11008 window->assertNoEvents();
11009}
11010
11011/**
11012 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11013 * in the middle of the gesture.
11014 */
11015TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11016 auto window = createForeground();
11017 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011018 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011019
11020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011021 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11023 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11024 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11025
11026 window->releaseChannel();
11027
11028 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11029
11030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011031 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11033 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11034}
11035
11036/**
11037 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11038 * the spy, but not to any other windows.
11039 */
11040TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11041 auto spy = createSpy();
11042 auto window = createForeground();
11043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011044 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011045
11046 // First finger down on the window and the spy.
11047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011048 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011049 {100, 200}))
11050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11051 spy->consumeMotionDown();
11052 window->consumeMotionDown();
11053
11054 // Spy window pilfers the pointers.
11055 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11056 window->consumeMotionCancel();
11057
11058 // Second finger down on the window and spy, but the window should not receive the pointer down.
11059 const MotionEvent secondFingerDownEvent =
11060 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11061 .displayId(ADISPLAY_ID_DEFAULT)
11062 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011063 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11064 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011065 .build();
11066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011067 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011068 InputEventInjectionSync::WAIT_FOR_RESULT))
11069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11070
Harry Cutts33476232023-01-30 19:57:29 +000011071 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011072
11073 // Third finger goes down outside all windows, so injection should fail.
11074 const MotionEvent thirdFingerDownEvent =
11075 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11076 .displayId(ADISPLAY_ID_DEFAULT)
11077 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011078 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11079 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11080 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011081 .build();
11082 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011083 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011084 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011085 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011086
11087 spy->assertNoEvents();
11088 window->assertNoEvents();
11089}
11090
11091/**
11092 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11093 */
11094TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11095 auto spy = createSpy();
11096 spy->setFrame(Rect(0, 0, 100, 100));
11097 auto window = createForeground();
11098 window->setFrame(Rect(0, 0, 200, 200));
11099
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011100 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011101
11102 // First finger down on the window only
11103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011104 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011105 {150, 150}))
11106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11107 window->consumeMotionDown();
11108
11109 // Second finger down on the spy and window
11110 const MotionEvent secondFingerDownEvent =
11111 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11112 .displayId(ADISPLAY_ID_DEFAULT)
11113 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011114 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11115 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011116 .build();
11117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011118 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011119 InputEventInjectionSync::WAIT_FOR_RESULT))
11120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11121 spy->consumeMotionDown();
11122 window->consumeMotionPointerDown(1);
11123
11124 // Third finger down on the spy and window
11125 const MotionEvent thirdFingerDownEvent =
11126 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11127 .displayId(ADISPLAY_ID_DEFAULT)
11128 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011129 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11130 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11131 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011132 .build();
11133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011134 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011135 InputEventInjectionSync::WAIT_FOR_RESULT))
11136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11137 spy->consumeMotionPointerDown(1);
11138 window->consumeMotionPointerDown(2);
11139
11140 // Spy window pilfers the pointers.
11141 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011142 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11143 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011144
11145 spy->assertNoEvents();
11146 window->assertNoEvents();
11147}
11148
11149/**
11150 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11151 * other windows should be canceled. If this results in the cancellation of all pointers for some
11152 * window, then that window should receive ACTION_CANCEL.
11153 */
11154TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11155 auto spy = createSpy();
11156 spy->setFrame(Rect(0, 0, 100, 100));
11157 auto window = createForeground();
11158 window->setFrame(Rect(0, 0, 200, 200));
11159
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011160 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011161
11162 // First finger down on both spy and window
11163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011164 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011165 {10, 10}))
11166 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11167 window->consumeMotionDown();
11168 spy->consumeMotionDown();
11169
11170 // Second finger down on the spy and window
11171 const MotionEvent secondFingerDownEvent =
11172 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11173 .displayId(ADISPLAY_ID_DEFAULT)
11174 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011175 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11176 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011177 .build();
11178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011179 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011180 InputEventInjectionSync::WAIT_FOR_RESULT))
11181 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11182 spy->consumeMotionPointerDown(1);
11183 window->consumeMotionPointerDown(1);
11184
11185 // Spy window pilfers the pointers.
11186 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11187 window->consumeMotionCancel();
11188
11189 spy->assertNoEvents();
11190 window->assertNoEvents();
11191}
11192
11193/**
11194 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11195 * be sent to other windows
11196 */
11197TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11198 auto spy = createSpy();
11199 spy->setFrame(Rect(0, 0, 100, 100));
11200 auto window = createForeground();
11201 window->setFrame(Rect(0, 0, 200, 200));
11202
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011203 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011204
11205 // First finger down on both window and spy
11206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011207 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011208 {10, 10}))
11209 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11210 window->consumeMotionDown();
11211 spy->consumeMotionDown();
11212
11213 // Spy window pilfers the pointers.
11214 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11215 window->consumeMotionCancel();
11216
11217 // Second finger down on the window only
11218 const MotionEvent secondFingerDownEvent =
11219 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11220 .displayId(ADISPLAY_ID_DEFAULT)
11221 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011222 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11223 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011224 .build();
11225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011226 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011227 InputEventInjectionSync::WAIT_FOR_RESULT))
11228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11229 window->consumeMotionDown();
11230 window->assertNoEvents();
11231
11232 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11233 spy->consumeMotionMove();
11234 spy->assertNoEvents();
11235}
11236
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011237/**
11238 * A window on the left and a window on the right. Also, a spy window that's above all of the
11239 * windows, and spanning both left and right windows.
11240 * Send simultaneous motion streams from two different devices, one to the left window, and another
11241 * to the right window.
11242 * Pilfer from spy window.
11243 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11244 */
11245TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11246 sp<FakeWindowHandle> spy = createSpy();
11247 spy->setFrame(Rect(0, 0, 200, 200));
11248 sp<FakeWindowHandle> leftWindow = createForeground();
11249 leftWindow->setFrame(Rect(0, 0, 100, 100));
11250
11251 sp<FakeWindowHandle> rightWindow = createForeground();
11252 rightWindow->setFrame(Rect(100, 0, 200, 100));
11253
11254 constexpr int32_t stylusDeviceId = 1;
11255 constexpr int32_t touchDeviceId = 2;
11256
11257 mDispatcher->onWindowInfosChanged(
11258 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11259
11260 // Stylus down on left window and spy
11261 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11262 .deviceId(stylusDeviceId)
11263 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11264 .build());
11265 leftWindow->consumeMotionEvent(
11266 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11267 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11268
11269 // Finger down on right window and spy - but spy already has stylus
11270 mDispatcher->notifyMotion(
11271 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11272 .deviceId(touchDeviceId)
11273 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11274 .build());
11275 rightWindow->consumeMotionEvent(
11276 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011277 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011278
11279 // Act: pilfer from spy. Spy is currently receiving touch events.
11280 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011281 leftWindow->consumeMotionEvent(
11282 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011283 rightWindow->consumeMotionEvent(
11284 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11285
11286 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11287 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11288 .deviceId(stylusDeviceId)
11289 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11290 .build());
11291 mDispatcher->notifyMotion(
11292 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11293 .deviceId(touchDeviceId)
11294 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11295 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011296 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011297
11298 spy->assertNoEvents();
11299 leftWindow->assertNoEvents();
11300 rightWindow->assertNoEvents();
11301}
11302
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011303TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11304 auto window = createForeground();
11305 auto spy = createSpy();
11306 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11307
11308 mDispatcher->notifyMotion(
11309 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11310 .deviceId(1)
11311 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11312 .build());
11313 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11314 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11315
11316 // Pilfer pointers from the spy window should fail.
11317 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11318 spy->assertNoEvents();
11319 window->assertNoEvents();
11320}
11321
Prabir Pradhand65552b2021-10-07 11:23:50 -070011322class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11323public:
11324 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11325 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11326 std::make_shared<FakeApplicationHandle>();
11327 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011328 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11329 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011330 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011331 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011332 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011333 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011334 overlay->setTrustedOverlay(true);
11335
11336 std::shared_ptr<FakeApplicationHandle> application =
11337 std::make_shared<FakeApplicationHandle>();
11338 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011339 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11340 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011341 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011342 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011343
11344 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011345 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011346 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011347 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011348 return {std::move(overlay), std::move(window)};
11349 }
11350
11351 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011352 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011353 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011354 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011355 }
11356
11357 void sendStylusEvent(int32_t action) {
11358 NotifyMotionArgs motionArgs =
11359 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11360 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011361 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011362 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011363 }
11364};
11365
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011366using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11367
11368TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011369 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011370 ScopedSilentDeath _silentDeath;
11371
Prabir Pradhand65552b2021-10-07 11:23:50 -070011372 auto [overlay, window] = setupStylusOverlayScenario();
11373 overlay->setTrustedOverlay(false);
11374 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011375 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11376 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011377 ".* not a trusted overlay");
11378}
11379
11380TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11381 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011382 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011383
11384 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11385 overlay->consumeMotionDown();
11386 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11387 overlay->consumeMotionUp();
11388
11389 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11390 window->consumeMotionDown();
11391 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11392 window->consumeMotionUp();
11393
11394 overlay->assertNoEvents();
11395 window->assertNoEvents();
11396}
11397
11398TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11399 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011400 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011401 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011402
11403 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11404 overlay->consumeMotionDown();
11405 window->consumeMotionDown();
11406 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11407 overlay->consumeMotionUp();
11408 window->consumeMotionUp();
11409
11410 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11411 window->consumeMotionDown();
11412 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11413 window->consumeMotionUp();
11414
11415 overlay->assertNoEvents();
11416 window->assertNoEvents();
11417}
11418
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011419/**
11420 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11421 * The scenario is as follows:
11422 * - The stylus interceptor overlay is configured as a spy window.
11423 * - The stylus interceptor spy receives the start of a new stylus gesture.
11424 * - It pilfers pointers and then configures itself to no longer be a spy.
11425 * - The stylus interceptor continues to receive the rest of the gesture.
11426 */
11427TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11428 auto [overlay, window] = setupStylusOverlayScenario();
11429 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011430 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011431
11432 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11433 overlay->consumeMotionDown();
11434 window->consumeMotionDown();
11435
11436 // The interceptor pilfers the pointers.
11437 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11438 window->consumeMotionCancel();
11439
11440 // The interceptor configures itself so that it is no longer a spy.
11441 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011442 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011443
11444 // It continues to receive the rest of the stylus gesture.
11445 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11446 overlay->consumeMotionMove();
11447 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11448 overlay->consumeMotionUp();
11449
11450 window->assertNoEvents();
11451}
11452
Prabir Pradhan5735a322022-04-11 17:23:34 +000011453struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011454 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011455 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011456 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11457 std::unique_ptr<InputDispatcher>& mDispatcher;
11458
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011459 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011460 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11461
11462 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011463 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011464 ADISPLAY_ID_DEFAULT, {100, 200},
11465 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11466 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11467 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11468 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11469 }
11470
11471 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011472 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011473 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011474 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011475 mPolicyFlags);
11476 }
11477
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011478 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011479 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11480 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011481 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11482 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011483 window->setOwnerInfo(mPid, mUid);
11484 return window;
11485 }
11486};
11487
11488using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11489
11490TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011491 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011492 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011493 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011494
11495 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11496 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11497 window->consumeMotionDown();
11498
11499 setFocusedWindow(window);
11500 window->consumeFocusEvent(true);
11501
11502 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11503 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11504 window->consumeKeyDown(ADISPLAY_ID_NONE);
11505}
11506
11507TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011508 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011509 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011511
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011512 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011513 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11514 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11515
11516 setFocusedWindow(window);
11517 window->consumeFocusEvent(true);
11518
11519 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11520 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11521 window->assertNoEvents();
11522}
11523
11524TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011525 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011526 auto window = owner.createWindow("Owned window");
11527 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011528 spy->setSpy(true);
11529 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011530 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011531
11532 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11533 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11534 spy->consumeMotionDown();
11535 window->consumeMotionDown();
11536}
11537
11538TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011539 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011540 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011541
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011542 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011543 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011544 randosSpy->setSpy(true);
11545 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011546 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011547
11548 // The event is targeted at owner's window, so injection should succeed, but the spy should
11549 // not receive the event.
11550 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11551 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11552 randosSpy->assertNoEvents();
11553 window->consumeMotionDown();
11554}
11555
11556TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011557 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011558 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011559
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011560 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011561 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011562 randosSpy->setSpy(true);
11563 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011564 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011565
11566 // A user that has injection permission can inject into any window.
11567 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011568 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011569 ADISPLAY_ID_DEFAULT));
11570 randosSpy->consumeMotionDown();
11571 window->consumeMotionDown();
11572
11573 setFocusedWindow(randosSpy);
11574 randosSpy->consumeFocusEvent(true);
11575
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011576 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011577 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11578 window->assertNoEvents();
11579}
11580
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011581TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011582 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011583 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011584
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011585 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011586 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011587 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11588 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011589 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011590
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011591 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011592 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11593 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11594 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011595 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011596}
11597
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011598using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11599
11600TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11602
11603 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11604 ADISPLAY_ID_DEFAULT);
11605 left->setFrame(Rect(0, 0, 100, 100));
11606 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11607 "Right Window", ADISPLAY_ID_DEFAULT);
11608 right->setFrame(Rect(100, 0, 200, 100));
11609 sp<FakeWindowHandle> spy =
11610 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11611 spy->setFrame(Rect(0, 0, 200, 100));
11612 spy->setTrustedOverlay(true);
11613 spy->setSpy(true);
11614
11615 mDispatcher->onWindowInfosChanged(
11616 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11617
11618 // Hover into the left window.
11619 mDispatcher->notifyMotion(
11620 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11621 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11622 .build());
11623
11624 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11625 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11626
11627 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11628 /*pointerId=*/0));
11629 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11630 /*pointerId=*/0));
11631 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11632 /*pointerId=*/0));
11633
11634 // Hover move to the right window.
11635 mDispatcher->notifyMotion(
11636 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11637 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11638 .build());
11639
11640 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11641 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11642 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11643
11644 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11645 /*pointerId=*/0));
11646 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11647 /*pointerId=*/0));
11648 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11649 /*pointerId=*/0));
11650
11651 // Stop hovering.
11652 mDispatcher->notifyMotion(
11653 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11654 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11655 .build());
11656
11657 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11658 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11659
11660 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11661 /*pointerId=*/0));
11662 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11663 /*pointerId=*/0));
11664 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11665 /*pointerId=*/0));
11666}
11667
11668TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11670
11671 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11672 ADISPLAY_ID_DEFAULT);
11673 left->setFrame(Rect(0, 0, 100, 100));
11674 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11675 "Right Window", ADISPLAY_ID_DEFAULT);
11676 right->setFrame(Rect(100, 0, 200, 100));
11677 sp<FakeWindowHandle> spy =
11678 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11679 spy->setFrame(Rect(0, 0, 200, 100));
11680 spy->setTrustedOverlay(true);
11681 spy->setSpy(true);
11682
11683 mDispatcher->onWindowInfosChanged(
11684 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11685
11686 // First pointer down on left window.
11687 mDispatcher->notifyMotion(
11688 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11689 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11690 .build());
11691
11692 left->consumeMotionDown();
11693 spy->consumeMotionDown();
11694
11695 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11696 /*pointerId=*/0));
11697 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11698 /*pointerId=*/0));
11699 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11700 /*pointerId=*/0));
11701
11702 // Second pointer down on right window.
11703 mDispatcher->notifyMotion(
11704 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11705 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11706 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11707 .build());
11708
11709 left->consumeMotionMove();
11710 right->consumeMotionDown();
11711 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11712
11713 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11714 /*pointerId=*/0));
11715 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11716 /*pointerId=*/0));
11717 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11718 /*pointerId=*/0));
11719 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11720 /*pointerId=*/1));
11721 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11722 /*pointerId=*/1));
11723 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11724 /*pointerId=*/1));
11725
11726 // Second pointer up.
11727 mDispatcher->notifyMotion(
11728 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11729 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11730 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11731 .build());
11732
11733 left->consumeMotionMove();
11734 right->consumeMotionUp();
11735 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11736
11737 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11738 /*pointerId=*/0));
11739 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11740 /*pointerId=*/0));
11741 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11742 /*pointerId=*/0));
11743 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11744 /*pointerId=*/1));
11745 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11746 /*pointerId=*/1));
11747 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11748 /*pointerId=*/1));
11749
11750 // First pointer up.
11751 mDispatcher->notifyMotion(
11752 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11753 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11754 .build());
11755
11756 left->consumeMotionUp();
11757 spy->consumeMotionUp();
11758
11759 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11760 /*pointerId=*/0));
11761 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11762 /*pointerId=*/0));
11763 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11764 /*pointerId=*/0));
11765}
11766
11767TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11769
11770 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11771 ADISPLAY_ID_DEFAULT);
11772 left->setFrame(Rect(0, 0, 100, 100));
11773 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11774 "Right Window", ADISPLAY_ID_DEFAULT);
11775 right->setFrame(Rect(100, 0, 200, 100));
11776
11777 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11778
11779 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11780 /*pointerId=*/0));
11781 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11782 /*pointerId=*/0));
11783
11784 // Hover move into the window.
11785 mDispatcher->notifyMotion(
11786 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11787 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11788 .rawXCursorPosition(50)
11789 .rawYCursorPosition(50)
11790 .deviceId(DEVICE_ID)
11791 .build());
11792
11793 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11794
11795 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11796 /*pointerId=*/0));
11797
11798 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11799 mDispatcher->notifyMotion(
11800 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11801 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11802 .rawXCursorPosition(51)
11803 .rawYCursorPosition(50)
11804 .deviceId(SECOND_DEVICE_ID)
11805 .build());
11806
11807 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11808 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11809
11810 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11811 // a HOVER_EXIT from the first device.
11812 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11813 /*pointerId=*/0));
11814 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11815 SECOND_DEVICE_ID,
11816 /*pointerId=*/0));
11817
11818 // Move the mouse outside the window. Document the current behavior, where the window does not
11819 // receive HOVER_EXIT even though the mouse left the window.
11820 mDispatcher->notifyMotion(
11821 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11822 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11823 .rawXCursorPosition(150)
11824 .rawYCursorPosition(50)
11825 .deviceId(SECOND_DEVICE_ID)
11826 .build());
11827
11828 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11829 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11830 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11831 /*pointerId=*/0));
11832 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11833 SECOND_DEVICE_ID,
11834 /*pointerId=*/0));
11835}
11836
Garfield Tane84e6f92019-08-29 17:28:41 -070011837} // namespace android::inputdispatcher