blob: ef07540eb9064a2b9dc3d72b4bacb21207d517f5 [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
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600552 void interceptMotionBeforeQueueing(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
Jackal Guof9696682018-10-05 12:23:23 +08007335class InputFilterTest : public InputDispatcherTest {
7336protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007337 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7338 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007339 NotifyMotionArgs motionArgs;
7340
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007341 motionArgs =
7342 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007343 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007344 motionArgs =
7345 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007346 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007347 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007348 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007349 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007350 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007351 } else {
7352 mFakePolicy->assertFilterInputEventWasNotCalled();
7353 }
7354 }
7355
7356 void testNotifyKey(bool expectToBeFiltered) {
7357 NotifyKeyArgs keyArgs;
7358
7359 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007360 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007361 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007362 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007363 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007364
7365 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007366 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007367 } else {
7368 mFakePolicy->assertFilterInputEventWasNotCalled();
7369 }
7370 }
7371};
7372
7373// Test InputFilter for MotionEvent
7374TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7375 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007376 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7377 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007378
7379 // Enable InputFilter
7380 mDispatcher->setInputFilterEnabled(true);
7381 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007382 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7383 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007384
7385 // Disable InputFilter
7386 mDispatcher->setInputFilterEnabled(false);
7387 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007388 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7389 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007390}
7391
7392// Test InputFilter for KeyEvent
7393TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7394 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007395 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007396
7397 // Enable InputFilter
7398 mDispatcher->setInputFilterEnabled(true);
7399 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007400 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007401
7402 // Disable InputFilter
7403 mDispatcher->setInputFilterEnabled(false);
7404 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007405 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007406}
7407
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007408// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7409// logical display coordinate space.
7410TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7411 ui::Transform firstDisplayTransform;
7412 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7413 ui::Transform secondDisplayTransform;
7414 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7415
7416 std::vector<gui::DisplayInfo> displayInfos(2);
7417 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7418 displayInfos[0].transform = firstDisplayTransform;
7419 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7420 displayInfos[1].transform = secondDisplayTransform;
7421
Patrick Williamsd828f302023-04-28 17:52:08 -05007422 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007423
7424 // Enable InputFilter
7425 mDispatcher->setInputFilterEnabled(true);
7426
7427 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007428 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7429 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007430}
7431
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007432class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7433protected:
7434 virtual void SetUp() override {
7435 InputDispatcherTest::SetUp();
7436
7437 /**
7438 * We don't need to enable input filter to test the injected event policy, but we enabled it
7439 * here to make the tests more realistic, since this policy only matters when inputfilter is
7440 * on.
7441 */
7442 mDispatcher->setInputFilterEnabled(true);
7443
7444 std::shared_ptr<InputApplicationHandle> application =
7445 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007446 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7447 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007448
7449 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7450 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007451 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007452 setFocusedWindow(mWindow);
7453 mWindow->consumeFocusEvent(true);
7454 }
7455
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007456 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7457 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007458 KeyEvent event;
7459
7460 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7461 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7462 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007463 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007464 const int32_t additionalPolicyFlags =
7465 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007467 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007468 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007469 policyFlags | additionalPolicyFlags));
7470
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007471 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007472 }
7473
7474 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7475 int32_t flags) {
7476 MotionEvent event;
7477 PointerProperties pointerProperties[1];
7478 PointerCoords pointerCoords[1];
7479 pointerProperties[0].clear();
7480 pointerProperties[0].id = 0;
7481 pointerCoords[0].clear();
7482 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7483 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7484
7485 ui::Transform identityTransform;
7486 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7487 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7488 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7489 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7490 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007491 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007492 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007493 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007494
7495 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007497 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007498 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007499 policyFlags | additionalPolicyFlags));
7500
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007501 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007502 }
7503
7504private:
7505 sp<FakeWindowHandle> mWindow;
7506};
7507
7508TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007509 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7510 // filter. Without it, the event will no different from a regularly injected event, and the
7511 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007512 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7513 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007514}
7515
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007516TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007517 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007518 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007519 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7520}
7521
7522TEST_F(InputFilterInjectionPolicyTest,
7523 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7524 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007525 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007526 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007527}
7528
7529TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007530 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7531 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007532}
7533
chaviwfd6d3512019-03-25 13:23:49 -07007534class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007535 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007536 InputDispatcherTest::SetUp();
7537
Chris Yea209fde2020-07-22 13:54:51 -07007538 std::shared_ptr<FakeApplicationHandle> application =
7539 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007540 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007541 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007542 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007543
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007544 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007545 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007546 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007547
7548 // Set focused application.
7549 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007550 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007551
7552 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007553 mDispatcher->onWindowInfosChanged(
7554 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007555 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007556 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007557 }
7558
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007559 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007560 InputDispatcherTest::TearDown();
7561
7562 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007563 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007564 }
7565
7566protected:
7567 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007568 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007569 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007570};
7571
7572// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7573// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7574// the onPointerDownOutsideFocus callback.
7575TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007577 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007578 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007580 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007581
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007582 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007583 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7584}
7585
7586// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7587// DOWN on the window that doesn't have focus. Ensure no window received the
7588// onPointerDownOutsideFocus callback.
7589TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007591 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7592 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007594 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007595
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007596 ASSERT_TRUE(mDispatcher->waitForIdle());
7597 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007598}
7599
7600// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7601// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7602TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007604 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007605 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007606 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007607
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007608 ASSERT_TRUE(mDispatcher->waitForIdle());
7609 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007610}
7611
7612// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7613// DOWN on the window that already has focus. Ensure no window received the
7614// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007615TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007617 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007618 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007620 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007621
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007622 ASSERT_TRUE(mDispatcher->waitForIdle());
7623 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007624}
7625
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007626// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7627// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7628TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7629 const MotionEvent event =
7630 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7631 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007632 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007633 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7634 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7637 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7638
7639 ASSERT_TRUE(mDispatcher->waitForIdle());
7640 mFakePolicy->assertOnPointerDownWasNotCalled();
7641 // Ensure that the unfocused window did not receive any FOCUS events.
7642 mUnfocusedWindow->assertNoEvents();
7643}
7644
chaviwaf87b3e2019-10-01 16:59:28 -07007645// These tests ensures we can send touch events to a single client when there are multiple input
7646// windows that point to the same client token.
7647class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7648 virtual void SetUp() override {
7649 InputDispatcherTest::SetUp();
7650
Chris Yea209fde2020-07-22 13:54:51 -07007651 std::shared_ptr<FakeApplicationHandle> application =
7652 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007653 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7654 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007655 mWindow1->setFrame(Rect(0, 0, 100, 100));
7656
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007657 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7658 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007659 mWindow2->setFrame(Rect(100, 100, 200, 200));
7660
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007661 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007662 }
7663
7664protected:
7665 sp<FakeWindowHandle> mWindow1;
7666 sp<FakeWindowHandle> mWindow2;
7667
7668 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007669 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007670 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7671 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007672 }
7673
7674 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7675 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007676 const std::string name = window->getName();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007677 const MotionEvent& motionEvent =
7678 window->consumeMotionEvent(WithMotionAction(expectedAction));
chaviwaf87b3e2019-10-01 16:59:28 -07007679
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007680 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007681
7682 for (size_t i = 0; i < points.size(); i++) {
7683 float expectedX = points[i].x;
7684 float expectedY = points[i].y;
7685
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007686 EXPECT_EQ(expectedX, motionEvent.getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007687 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007688 << ", got " << motionEvent.getX(i);
7689 EXPECT_EQ(expectedY, motionEvent.getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007690 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007691 << ", got " << motionEvent.getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007692 }
7693 }
chaviw9eaa22c2020-07-01 16:21:27 -07007694
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007695 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007696 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007697 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7698 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007699
7700 // Always consume from window1 since it's the window that has the InputReceiver
7701 consumeMotionEvent(mWindow1, action, expectedPoints);
7702 }
chaviwaf87b3e2019-10-01 16:59:28 -07007703};
7704
7705TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7706 // Touch Window 1
7707 PointF touchedPoint = {10, 10};
7708 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007709 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007710
7711 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007712 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007713
7714 // Touch Window 2
7715 touchedPoint = {150, 150};
7716 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007717 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007718}
7719
chaviw9eaa22c2020-07-01 16:21:27 -07007720TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7721 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007722 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007723 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007724
7725 // Touch Window 1
7726 PointF touchedPoint = {10, 10};
7727 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007728 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007729 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007730 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007731
7732 // Touch Window 2
7733 touchedPoint = {150, 150};
7734 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007735 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7736 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007737
chaviw9eaa22c2020-07-01 16:21:27 -07007738 // Update the transform so rotation is set
7739 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007740 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007741 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7742 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007743}
7744
chaviw9eaa22c2020-07-01 16:21:27 -07007745TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007746 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007747 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007748
7749 // Touch Window 1
7750 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7751 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007752 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007753
7754 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007755 touchedPoints.push_back(PointF{150, 150});
7756 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007757 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007758
chaviw9eaa22c2020-07-01 16:21:27 -07007759 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007760 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007761 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007762
chaviw9eaa22c2020-07-01 16:21:27 -07007763 // Update the transform so rotation is set for Window 2
7764 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007765 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007766 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007767 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007768}
7769
chaviw9eaa22c2020-07-01 16:21:27 -07007770TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007771 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007772 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007773
7774 // Touch Window 1
7775 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7776 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007777 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007778
7779 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007780 touchedPoints.push_back(PointF{150, 150});
7781 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007782
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007783 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007784
7785 // Move both windows
7786 touchedPoints = {{20, 20}, {175, 175}};
7787 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7788 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7789
chaviw9eaa22c2020-07-01 16:21:27 -07007790 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007791
chaviw9eaa22c2020-07-01 16:21:27 -07007792 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007793 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007794 expectedPoints.pop_back();
7795
7796 // Touch Window 2
7797 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007798 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007799 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007800 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007801
7802 // Move both windows
7803 touchedPoints = {{20, 20}, {175, 175}};
7804 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7805 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7806
7807 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007808}
7809
7810TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7811 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007812 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007813
7814 // Touch Window 1
7815 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7816 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007817 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007818
7819 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007820 touchedPoints.push_back(PointF{150, 150});
7821 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007822
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007823 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007824
7825 // Move both windows
7826 touchedPoints = {{20, 20}, {175, 175}};
7827 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7828 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7829
chaviw9eaa22c2020-07-01 16:21:27 -07007830 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007831}
7832
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007833/**
7834 * When one of the windows is slippery, the touch should not slip into the other window with the
7835 * same input channel.
7836 */
7837TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7838 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007839 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007840
7841 // Touch down in window 1
7842 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7843 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7844 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7845
7846 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7847 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7848 // getting generated.
7849 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7850 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7851
7852 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7853}
7854
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007855/**
7856 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7857 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7858 * that the pointer is hovering over may have a different transform.
7859 */
7860TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007861 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007862
7863 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007864 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7865 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7866 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007867 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7868 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007869 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7871 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7872 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007873 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7874 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7875 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7876}
7877
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007878class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7879 virtual void SetUp() override {
7880 InputDispatcherTest::SetUp();
7881
Chris Yea209fde2020-07-22 13:54:51 -07007882 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007883 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007884 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7885 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007886 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007887 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007888 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007889
7890 // Set focused application.
7891 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7892
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007893 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007894 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007895 mWindow->consumeFocusEvent(true);
7896 }
7897
7898 virtual void TearDown() override {
7899 InputDispatcherTest::TearDown();
7900 mWindow.clear();
7901 }
7902
7903protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007904 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007905 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007906 sp<FakeWindowHandle> mWindow;
7907 static constexpr PointF WINDOW_LOCATION = {20, 20};
7908
7909 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007910 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7911 .x(WINDOW_LOCATION.x)
7912 .y(WINDOW_LOCATION.y);
7913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7914 .pointer(touchingPointer)
7915 .build());
7916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7917 .pointer(touchingPointer)
7918 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007919 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007920
7921 sp<FakeWindowHandle> addSpyWindow() {
7922 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007923 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007924 spy->setTrustedOverlay(true);
7925 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007926 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007927 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007928 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007929 return spy;
7930 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007931};
7932
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007933// Send a tap and respond, which should not cause an ANR.
7934TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7935 tapOnWindow();
7936 mWindow->consumeMotionDown();
7937 mWindow->consumeMotionUp();
7938 ASSERT_TRUE(mDispatcher->waitForIdle());
7939 mFakePolicy->assertNotifyAnrWasNotCalled();
7940}
7941
7942// Send a regular key and respond, which should not cause an ANR.
7943TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007945 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7946 ASSERT_TRUE(mDispatcher->waitForIdle());
7947 mFakePolicy->assertNotifyAnrWasNotCalled();
7948}
7949
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007950TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7951 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007952 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007953 mWindow->consumeFocusEvent(false);
7954
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007955 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007956 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7957 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007958 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007960 // Key will not go to window because we have no focused window.
7961 // The 'no focused window' ANR timer should start instead.
7962
7963 // Now, the focused application goes away.
7964 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7965 // The key should get dropped and there should be no ANR.
7966
7967 ASSERT_TRUE(mDispatcher->waitForIdle());
7968 mFakePolicy->assertNotifyAnrWasNotCalled();
7969}
7970
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007971// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007972// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7973// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007974TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007976 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007977 WINDOW_LOCATION));
7978
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007979 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7980 ASSERT_TRUE(sequenceNum);
7981 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007982 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007983
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007984 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007985 mWindow->consumeMotionEvent(
7986 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007987 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007988 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007989}
7990
7991// Send a key to the app and have the app not respond right away.
7992TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
7993 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007995 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
7996 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007997 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007998 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007999 ASSERT_TRUE(mDispatcher->waitForIdle());
8000}
8001
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008002// We have a focused application, but no focused window
8003TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008004 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008005 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008006 mWindow->consumeFocusEvent(false);
8007
8008 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008010 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008011 WINDOW_LOCATION));
8012 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8013 mDispatcher->waitForIdle();
8014 mFakePolicy->assertNotifyAnrWasNotCalled();
8015
8016 // Once a focused event arrives, we get an ANR for this application
8017 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8018 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008019 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008020 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008021 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008022 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008023 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008024 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008025 ASSERT_TRUE(mDispatcher->waitForIdle());
8026}
8027
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008028/**
8029 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8030 * there will not be an ANR.
8031 */
8032TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8033 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008034 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008035 mWindow->consumeFocusEvent(false);
8036
8037 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008038 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8039 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008040 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8041 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8042
8043 // Define a valid key down event that is stale (too old).
8044 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008045 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008046 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008047
8048 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8049
8050 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008051 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008052 InputEventInjectionSync::WAIT_FOR_RESULT,
8053 INJECT_EVENT_TIMEOUT, policyFlags);
8054 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8055 << "Injection should fail because the event is stale";
8056
8057 ASSERT_TRUE(mDispatcher->waitForIdle());
8058 mFakePolicy->assertNotifyAnrWasNotCalled();
8059 mWindow->assertNoEvents();
8060}
8061
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008062// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008063// Make sure that we don't notify policy twice about the same ANR.
8064TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008065 const std::chrono::duration appTimeout = 400ms;
8066 mApplication->setDispatchingTimeout(appTimeout);
8067 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8068
Vishnu Nair47074b82020-08-14 11:54:47 -07008069 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008070 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008071 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008072
8073 // Once a focused event arrives, we get an ANR for this application
8074 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8075 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008076 const std::chrono::duration eventInjectionTimeout = 100ms;
8077 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008078 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008079 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008080 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8081 /*allowKeyRepeat=*/false);
8082 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8083 << "result=" << ftl::enum_string(result);
8084 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8085 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8086 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8087 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008088
Vishnu Naire4df8752022-09-08 09:17:55 -07008089 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008090 // ANR should not be raised again. It is up to policy to do that if it desires.
8091 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008092
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008093 // If we now get a focused window, the ANR should stop, but the policy handles that via
8094 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008095 ASSERT_TRUE(mDispatcher->waitForIdle());
8096}
8097
8098// We have a focused application, but no focused window
8099TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008100 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008101 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008102 mWindow->consumeFocusEvent(false);
8103
8104 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008105 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008106
Vishnu Naire4df8752022-09-08 09:17:55 -07008107 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8108 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008109
8110 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008111 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008112 ASSERT_TRUE(mDispatcher->waitForIdle());
8113 mWindow->assertNoEvents();
8114}
8115
8116/**
8117 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8118 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8119 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8120 * the ANR mechanism should still work.
8121 *
8122 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8123 * DOWN event, while not responding on the second one.
8124 */
8125TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8126 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008127 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008128 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8129 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8130 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008131 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008132
8133 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008134 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008135 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8136 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8137 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008138 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008139
8140 // We have now sent down and up. Let's consume first event and then ANR on the second.
8141 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8142 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008143 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008144}
8145
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008146// A spy window can receive an ANR
8147TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8148 sp<FakeWindowHandle> spy = addSpyWindow();
8149
8150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008151 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008152 WINDOW_LOCATION));
8153 mWindow->consumeMotionDown();
8154
8155 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
8156 ASSERT_TRUE(sequenceNum);
8157 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008158 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008159
8160 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008161 spy->consumeMotionEvent(
8162 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008163 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008164 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008165}
8166
8167// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008168// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008169TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8170 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008171
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008173 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008174 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008176
8177 // Stuck on the ACTION_UP
8178 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008179 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008180
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008181 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008182 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008183 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8184 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008185
8186 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8187 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008188 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008189 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008190 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008191}
8192
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008193// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008194// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008195TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8196 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008197
8198 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008199 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8200 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008201
8202 mWindow->consumeMotionDown();
8203 // Stuck on the ACTION_UP
8204 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008205 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008206
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008207 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008208 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008209 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8210 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008211
8212 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8213 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008214 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008215 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008216 spy->assertNoEvents();
8217}
8218
8219TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008220 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008221
Prabir Pradhanfb549072023-10-05 19:17:36 +00008222 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008223
8224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008225 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008226 WINDOW_LOCATION));
8227
8228 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8229 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8230 ASSERT_TRUE(consumeSeq);
8231
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008232 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8233 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008234
8235 monitor.finishEvent(*consumeSeq);
8236 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8237
8238 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008239 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008240}
8241
8242// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8243// process events, you don't get an anr. When the window later becomes unresponsive again, you
8244// get an ANR again.
8245// 1. tap -> block on ACTION_UP -> receive ANR
8246// 2. consume all pending events (= queue becomes healthy again)
8247// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8248TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8249 tapOnWindow();
8250
8251 mWindow->consumeMotionDown();
8252 // Block on ACTION_UP
8253 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008254 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008255 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8256 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008257 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008258 mWindow->assertNoEvents();
8259
8260 tapOnWindow();
8261 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008262 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008263 mWindow->consumeMotionUp();
8264
8265 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008266 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008267 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008268 mWindow->assertNoEvents();
8269}
8270
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008271// If a connection remains unresponsive for a while, make sure policy is only notified once about
8272// it.
8273TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008275 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008276 WINDOW_LOCATION));
8277
8278 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008279 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008280 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008281 // 'notifyConnectionUnresponsive' should only be called once per connection
8282 mFakePolicy->assertNotifyAnrWasNotCalled();
8283 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008284 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008285 mWindow->consumeMotionEvent(
8286 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008287 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008288 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008289 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008290 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008291}
8292
8293/**
8294 * 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 -07008295 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008296 *
8297 * Warning!!!
8298 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8299 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008300 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008301 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8302 *
8303 * If that value changes, this test should also change.
8304 */
8305TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8306 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008307 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008308
8309 tapOnWindow();
8310 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8311 ASSERT_TRUE(downSequenceNum);
8312 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8313 ASSERT_TRUE(upSequenceNum);
8314 // Don't finish the events yet, and send a key
8315 // Injection will "succeed" because we will eventually give up and send the key to the focused
8316 // window even if motions are still being processed. But because the injection timeout is short,
8317 // we will receive INJECTION_TIMED_OUT as the result.
8318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008319 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008320 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8321 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008322 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008323 // Key will not be sent to the window, yet, because the window is still processing events
8324 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008325 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8326 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8327 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8328 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008329
8330 std::this_thread::sleep_for(500ms);
8331 // if we wait long enough though, dispatcher will give up, and still send the key
8332 // to the focused window, even though we have not yet finished the motion event
8333 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8334 mWindow->finishEvent(*downSequenceNum);
8335 mWindow->finishEvent(*upSequenceNum);
8336}
8337
8338/**
8339 * If a window is processing a motion event, and then a key event comes in, the key event should
8340 * not go to the focused window until the motion is processed.
8341 * If then a new motion comes in, then the pending key event should be going to the currently
8342 * focused window right away.
8343 */
8344TEST_F(InputDispatcherSingleWindowAnr,
8345 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8346 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008347 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008348
8349 tapOnWindow();
8350 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
8351 ASSERT_TRUE(downSequenceNum);
8352 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
8353 ASSERT_TRUE(upSequenceNum);
8354 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008355 mDispatcher->notifyKey(
8356 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8357 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8358 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008359 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008360 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8361 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8362 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8363 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008364
8365 // Now tap down again. It should cause the pending key to go to the focused window right away.
8366 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008367 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8368 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008369 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8370 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008371 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8372 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008373 mWindow->assertNoEvents();
8374}
8375
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008376/**
8377 * Send an event to the app and have the app not respond right away.
8378 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8379 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8380 * At some point, the window becomes responsive again.
8381 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8382 */
8383TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8384 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8385 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8386 .build());
8387
8388 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
8389 ASSERT_TRUE(sequenceNum);
8390 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8391 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8392
8393 mWindow->finishEvent(*sequenceNum);
8394 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8395 ASSERT_TRUE(mDispatcher->waitForIdle());
8396 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8397
8398 // Now that the window is responsive, let's continue the gesture.
8399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8400 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8401 .build());
8402
8403 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8404 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8405 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8406 .build());
8407
8408 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8409 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8410 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8411 .build());
8412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8413 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8414 .build());
8415 // We already canceled this pointer, so the window shouldn't get any new events.
8416 mWindow->assertNoEvents();
8417
8418 // Start another one.
8419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8420 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8421 .build());
8422 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8423}
8424
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008425class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8426 virtual void SetUp() override {
8427 InputDispatcherTest::SetUp();
8428
Chris Yea209fde2020-07-22 13:54:51 -07008429 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008430 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008431 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8432 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008433 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008434 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008435 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008436
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008437 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8438 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008439 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008440 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008441
8442 // Set focused application.
8443 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008444 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008445
8446 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008447 mDispatcher->onWindowInfosChanged(
8448 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008449 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008450 mFocusedWindow->consumeFocusEvent(true);
8451 }
8452
8453 virtual void TearDown() override {
8454 InputDispatcherTest::TearDown();
8455
8456 mUnfocusedWindow.clear();
8457 mFocusedWindow.clear();
8458 }
8459
8460protected:
Chris Yea209fde2020-07-22 13:54:51 -07008461 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008462 sp<FakeWindowHandle> mUnfocusedWindow;
8463 sp<FakeWindowHandle> mFocusedWindow;
8464 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8465 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8466 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8467
8468 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8469
8470 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8471
8472private:
8473 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008475 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008476 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008478 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008479 location));
8480 }
8481};
8482
8483// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8484// should be ANR'd first.
8485TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008487 injectMotionEvent(*mDispatcher,
8488 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8489 AINPUT_SOURCE_TOUCHSCREEN)
8490 .pointer(PointerBuilder(0, ToolType::FINGER)
8491 .x(FOCUSED_WINDOW_LOCATION.x)
8492 .y(FOCUSED_WINDOW_LOCATION.y))
8493 .build()));
8494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8495 injectMotionEvent(*mDispatcher,
8496 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8497 AINPUT_SOURCE_TOUCHSCREEN)
8498 .pointer(PointerBuilder(0, ToolType::FINGER)
8499 .x(FOCUSED_WINDOW_LOCATION.x)
8500 .y(FOCUSED_WINDOW_LOCATION.y))
8501 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008502 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008503 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008504 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008505 // We consumed all events, so no ANR
8506 ASSERT_TRUE(mDispatcher->waitForIdle());
8507 mFakePolicy->assertNotifyAnrWasNotCalled();
8508
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008510 injectMotionEvent(*mDispatcher,
8511 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8512 AINPUT_SOURCE_TOUCHSCREEN)
8513 .pointer(PointerBuilder(0, ToolType::FINGER)
8514 .x(FOCUSED_WINDOW_LOCATION.x)
8515 .y(FOCUSED_WINDOW_LOCATION.y))
8516 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008517 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
8518 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008519
8520 const std::chrono::duration timeout =
8521 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008522 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008523
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008524 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008525 mFocusedWindow->consumeMotionDown();
8526 // This cancel is generated because the connection was unresponsive
8527 mFocusedWindow->consumeMotionCancel();
8528 mFocusedWindow->assertNoEvents();
8529 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008530 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008531 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8532 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008533 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008534}
8535
8536// If we have 2 windows with identical timeouts that are both unresponsive,
8537// it doesn't matter which order they should have ANR.
8538// But we should receive ANR for both.
8539TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8540 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008541 mUnfocusedWindow->setDispatchingTimeout(
8542 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008543 mDispatcher->onWindowInfosChanged(
8544 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008545
8546 tapOnFocusedWindow();
8547 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008548 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008549 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8550 mFocusedWindow->getDispatchingTimeout(
8551 DISPATCHING_TIMEOUT)),
8552 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8553
8554 ASSERT_THAT(anrConnectionTokens,
8555 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8556 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008557
8558 ASSERT_TRUE(mDispatcher->waitForIdle());
8559 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008560
8561 mFocusedWindow->consumeMotionDown();
8562 mFocusedWindow->consumeMotionUp();
8563 mUnfocusedWindow->consumeMotionOutside();
8564
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008565 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8566 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008567
8568 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008569 ASSERT_THAT(responsiveTokens,
8570 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8571 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008572 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008573}
8574
8575// If a window is already not responding, the second tap on the same window should be ignored.
8576// We should also log an error to account for the dropped event (not tested here).
8577// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8578TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8579 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008580 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008581 // Receive the events, but don't respond
8582 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
8583 ASSERT_TRUE(downEventSequenceNum);
8584 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
8585 ASSERT_TRUE(upEventSequenceNum);
8586 const std::chrono::duration timeout =
8587 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008588 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008589
8590 // Tap once again
8591 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008592 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008593 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008594 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008595 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008596 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008597 FOCUSED_WINDOW_LOCATION));
8598 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8599 // valid touch target
8600 mUnfocusedWindow->assertNoEvents();
8601
8602 // Consume the first tap
8603 mFocusedWindow->finishEvent(*downEventSequenceNum);
8604 mFocusedWindow->finishEvent(*upEventSequenceNum);
8605 ASSERT_TRUE(mDispatcher->waitForIdle());
8606 // The second tap did not go to the focused window
8607 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008608 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008609 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8610 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008611 mFakePolicy->assertNotifyAnrWasNotCalled();
8612}
8613
8614// If you tap outside of all windows, there will not be ANR
8615TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008616 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008617 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008618 LOCATION_OUTSIDE_ALL_WINDOWS));
8619 ASSERT_TRUE(mDispatcher->waitForIdle());
8620 mFakePolicy->assertNotifyAnrWasNotCalled();
8621}
8622
8623// Since the focused window is paused, tapping on it should not produce any events
8624TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8625 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008626 mDispatcher->onWindowInfosChanged(
8627 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008628
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008629 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008630 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008631 FOCUSED_WINDOW_LOCATION));
8632
8633 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8634 ASSERT_TRUE(mDispatcher->waitForIdle());
8635 // Should not ANR because the window is paused, and touches shouldn't go to it
8636 mFakePolicy->assertNotifyAnrWasNotCalled();
8637
8638 mFocusedWindow->assertNoEvents();
8639 mUnfocusedWindow->assertNoEvents();
8640}
8641
8642/**
8643 * 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 -07008644 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008645 * If a different window becomes focused at this time, the key should go to that window instead.
8646 *
8647 * Warning!!!
8648 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8649 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008650 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008651 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8652 *
8653 * If that value changes, this test should also change.
8654 */
8655TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8656 // Set a long ANR timeout to prevent it from triggering
8657 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008658 mDispatcher->onWindowInfosChanged(
8659 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008660
8661 tapOnUnfocusedWindow();
8662 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
8663 ASSERT_TRUE(downSequenceNum);
8664 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
8665 ASSERT_TRUE(upSequenceNum);
8666 // Don't finish the events yet, and send a key
8667 // Injection will succeed because we will eventually give up and send the key to the focused
8668 // window even if motions are still being processed.
8669
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008670 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008671 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8672 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008674 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008675 // and the key remains pending, waiting for the touch events to be processed.
8676 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8677 // under the hood.
8678 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8679 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008680
8681 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008682 mFocusedWindow->setFocusable(false);
8683 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008684 mDispatcher->onWindowInfosChanged(
8685 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008686 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008687
8688 // Focus events should precede the key events
8689 mUnfocusedWindow->consumeFocusEvent(true);
8690 mFocusedWindow->consumeFocusEvent(false);
8691
8692 // Finish the tap events, which should unblock dispatcher
8693 mUnfocusedWindow->finishEvent(*downSequenceNum);
8694 mUnfocusedWindow->finishEvent(*upSequenceNum);
8695
8696 // Now that all queues are cleared and no backlog in the connections, the key event
8697 // can finally go to the newly focused "mUnfocusedWindow".
8698 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8699 mFocusedWindow->assertNoEvents();
8700 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008701 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008702}
8703
8704// When the touch stream is split across 2 windows, and one of them does not respond,
8705// then ANR should be raised and the touch should be canceled for the unresponsive window.
8706// The other window should not be affected by that.
8707TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8708 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008709 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8710 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8711 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008712 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008713
8714 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008715 mDispatcher->notifyMotion(
8716 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8717 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008718
8719 const std::chrono::duration timeout =
8720 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008721 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008722
8723 mUnfocusedWindow->consumeMotionDown();
8724 mFocusedWindow->consumeMotionDown();
8725 // Focused window may or may not receive ACTION_MOVE
8726 // But it should definitely receive ACTION_CANCEL due to the ANR
8727 InputEvent* event;
8728 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
8729 ASSERT_TRUE(moveOrCancelSequenceNum);
8730 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8731 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008732 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008733 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8734 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8735 mFocusedWindow->consumeMotionCancel();
8736 } else {
8737 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8738 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008739 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008740 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8741 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008742
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008743 mUnfocusedWindow->assertNoEvents();
8744 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008745 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008746}
8747
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008748/**
8749 * If we have no focused window, and a key comes in, we start the ANR timer.
8750 * The focused application should add a focused window before the timer runs out to prevent ANR.
8751 *
8752 * If the user touches another application during this time, the key should be dropped.
8753 * Next, if a new focused window comes in, without toggling the focused application,
8754 * then no ANR should occur.
8755 *
8756 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8757 * but in some cases the policy may not update the focused application.
8758 */
8759TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8760 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8761 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008762 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008763 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8764 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8765 mFocusedWindow->setFocusable(false);
8766
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008767 mDispatcher->onWindowInfosChanged(
8768 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008769 mFocusedWindow->consumeFocusEvent(false);
8770
8771 // Send a key. The ANR timer should start because there is no focused window.
8772 // 'focusedApplication' will get blamed if this timer completes.
8773 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008774 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008775 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8776 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008777 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008779
8780 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8781 // then the injected touches won't cause the focused event to get dropped.
8782 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8783 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8784 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8785 // For this test, it means that the key would get delivered to the window once it becomes
8786 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008787 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008788
8789 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008790 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8791 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8792 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008793
8794 // We do not consume the motion right away, because that would require dispatcher to first
8795 // process (== drop) the key event, and by that time, ANR will be raised.
8796 // Set the focused window first.
8797 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008798 mDispatcher->onWindowInfosChanged(
8799 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008800 setFocusedWindow(mFocusedWindow);
8801 mFocusedWindow->consumeFocusEvent(true);
8802 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8803 // to another application. This could be a bug / behaviour in the policy.
8804
8805 mUnfocusedWindow->consumeMotionDown();
8806
8807 ASSERT_TRUE(mDispatcher->waitForIdle());
8808 // Should not ANR because we actually have a focused window. It was just added too slowly.
8809 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8810}
8811
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008812// These tests ensure we cannot send touch events to a window that's positioned behind a window
8813// that has feature NO_INPUT_CHANNEL.
8814// Layout:
8815// Top (closest to user)
8816// mNoInputWindow (above all windows)
8817// mBottomWindow
8818// Bottom (furthest from user)
8819class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8820 virtual void SetUp() override {
8821 InputDispatcherTest::SetUp();
8822
8823 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008824 mNoInputWindow =
8825 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8826 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008827 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008828 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008829 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8830 // It's perfectly valid for this window to not have an associated input channel
8831
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008832 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8833 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008834 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008836 mDispatcher->onWindowInfosChanged(
8837 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008838 }
8839
8840protected:
8841 std::shared_ptr<FakeApplicationHandle> mApplication;
8842 sp<FakeWindowHandle> mNoInputWindow;
8843 sp<FakeWindowHandle> mBottomWindow;
8844};
8845
8846TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8847 PointF touchedPoint = {10, 10};
8848
Prabir Pradhan678438e2023-04-13 19:32:51 +00008849 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8850 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8851 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008852
8853 mNoInputWindow->assertNoEvents();
8854 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8855 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8856 // and therefore should prevent mBottomWindow from receiving touches
8857 mBottomWindow->assertNoEvents();
8858}
8859
8860/**
8861 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8862 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8863 */
8864TEST_F(InputDispatcherMultiWindowOcclusionTests,
8865 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008866 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8867 "Window with input channel and NO_INPUT_CHANNEL",
8868 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008869
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008870 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008871 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008872 mDispatcher->onWindowInfosChanged(
8873 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008874
8875 PointF touchedPoint = {10, 10};
8876
Prabir Pradhan678438e2023-04-13 19:32:51 +00008877 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8878 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8879 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008880
8881 mNoInputWindow->assertNoEvents();
8882 mBottomWindow->assertNoEvents();
8883}
8884
Vishnu Nair958da932020-08-21 17:12:37 -07008885class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8886protected:
8887 std::shared_ptr<FakeApplicationHandle> mApp;
8888 sp<FakeWindowHandle> mWindow;
8889 sp<FakeWindowHandle> mMirror;
8890
8891 virtual void SetUp() override {
8892 InputDispatcherTest::SetUp();
8893 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008894 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
8895 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
8896 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07008897 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8898 mWindow->setFocusable(true);
8899 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008900 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008901 }
8902};
8903
8904TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
8905 // Request focus on a mirrored window
8906 setFocusedWindow(mMirror);
8907
8908 // window gets focused
8909 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008911 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008912 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8913}
8914
8915// A focused & mirrored window remains focused only if the window and its mirror are both
8916// focusable.
8917TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
8918 setFocusedWindow(mMirror);
8919
8920 // window gets focused
8921 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008923 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008924 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008926 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008927 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8928
8929 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008930 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008931
8932 // window loses focus since one of the windows associated with the token in not focusable
8933 mWindow->consumeFocusEvent(false);
8934
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008935 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008936 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008937 mWindow->assertNoEvents();
8938}
8939
8940// A focused & mirrored window remains focused until the window and its mirror both become
8941// invisible.
8942TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
8943 setFocusedWindow(mMirror);
8944
8945 // window gets focused
8946 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008948 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008949 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008951 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008952 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8953
8954 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008955 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008956
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008958 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008959 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008961 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008962 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8963
8964 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008965 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008966
8967 // window loses focus only after all windows associated with the token become invisible.
8968 mWindow->consumeFocusEvent(false);
8969
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008970 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008971 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07008972 mWindow->assertNoEvents();
8973}
8974
8975// A focused & mirrored window remains focused until both windows are removed.
8976TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
8977 setFocusedWindow(mMirror);
8978
8979 // window gets focused
8980 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008982 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008983 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008985 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008986 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8987
8988 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008989 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008990
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008992 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008993 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008995 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008996 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
8997
8998 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008999 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009000 mWindow->consumeFocusEvent(false);
9001
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009002 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009003 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009004 mWindow->assertNoEvents();
9005}
9006
9007// Focus request can be pending until one window becomes visible.
9008TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9009 // Request focus on an invisible mirror.
9010 mWindow->setVisible(false);
9011 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009012 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009013 setFocusedWindow(mMirror);
9014
9015 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009017 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9018 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009019
9020 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009021 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009022
9023 // window gets focused
9024 mWindow->consumeFocusEvent(true);
9025 // window gets the pending key event
9026 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9027}
Prabir Pradhan99987712020-11-10 18:43:05 -08009028
9029class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9030protected:
9031 std::shared_ptr<FakeApplicationHandle> mApp;
9032 sp<FakeWindowHandle> mWindow;
9033 sp<FakeWindowHandle> mSecondWindow;
9034
9035 void SetUp() override {
9036 InputDispatcherTest::SetUp();
9037 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009038 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009039 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009040 mSecondWindow =
9041 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009042 mSecondWindow->setFocusable(true);
9043
9044 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009045 mDispatcher->onWindowInfosChanged(
9046 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009047
9048 setFocusedWindow(mWindow);
9049 mWindow->consumeFocusEvent(true);
9050 }
9051
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009052 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009053 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009054 }
9055
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009056 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9057 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009058 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009059 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9060 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009061 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009062 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009063 }
9064};
9065
9066TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9067 // Ensure that capture cannot be obtained for unfocused windows.
9068 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9069 mFakePolicy->assertSetPointerCaptureNotCalled();
9070 mSecondWindow->assertNoEvents();
9071
9072 // Ensure that capture can be enabled from the focus window.
9073 requestAndVerifyPointerCapture(mWindow, true);
9074
9075 // Ensure that capture cannot be disabled from a window that does not have capture.
9076 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9077 mFakePolicy->assertSetPointerCaptureNotCalled();
9078
9079 // Ensure that capture can be disabled from the window with capture.
9080 requestAndVerifyPointerCapture(mWindow, false);
9081}
9082
9083TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009084 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009085
9086 setFocusedWindow(mSecondWindow);
9087
9088 // Ensure that the capture disabled event was sent first.
9089 mWindow->consumeCaptureEvent(false);
9090 mWindow->consumeFocusEvent(false);
9091 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009092 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009093
9094 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009095 notifyPointerCaptureChanged({});
9096 notifyPointerCaptureChanged(request);
9097 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009098 mWindow->assertNoEvents();
9099 mSecondWindow->assertNoEvents();
9100 mFakePolicy->assertSetPointerCaptureNotCalled();
9101}
9102
9103TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009104 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009105
9106 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009107 notifyPointerCaptureChanged({});
9108 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009109
9110 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009111 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009112 mWindow->consumeCaptureEvent(false);
9113 mWindow->assertNoEvents();
9114}
9115
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009116TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9117 requestAndVerifyPointerCapture(mWindow, true);
9118
9119 // The first window loses focus.
9120 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009121 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009122 mWindow->consumeCaptureEvent(false);
9123
9124 // Request Pointer Capture from the second window before the notification from InputReader
9125 // arrives.
9126 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009127 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009128
9129 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009130 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009131
9132 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009133 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009134
9135 mSecondWindow->consumeFocusEvent(true);
9136 mSecondWindow->consumeCaptureEvent(true);
9137}
9138
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009139TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9140 // App repeatedly enables and disables capture.
9141 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9142 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9143 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9144 mFakePolicy->assertSetPointerCaptureCalled(false);
9145 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9146 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9147
9148 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9149 // first request is now stale, this should do nothing.
9150 notifyPointerCaptureChanged(firstRequest);
9151 mWindow->assertNoEvents();
9152
9153 // InputReader notifies that the second request was enabled.
9154 notifyPointerCaptureChanged(secondRequest);
9155 mWindow->consumeCaptureEvent(true);
9156}
9157
Prabir Pradhan7092e262022-05-03 16:51:09 +00009158TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9159 requestAndVerifyPointerCapture(mWindow, true);
9160
9161 // App toggles pointer capture off and on.
9162 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9163 mFakePolicy->assertSetPointerCaptureCalled(false);
9164
9165 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9166 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9167
9168 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9169 // preceding "disable" request.
9170 notifyPointerCaptureChanged(enableRequest);
9171
9172 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9173 // any notifications.
9174 mWindow->assertNoEvents();
9175}
9176
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009177/**
9178 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9179 * mouse movements don't affect the previous mouse hovering state.
9180 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9181 * HOVER_MOVE events).
9182 */
9183TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9184 // Mouse hover on the window
9185 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9186 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9187 .build());
9188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9189 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9190 .build());
9191
9192 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9193 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9194
9195 // Start pointer capture
9196 requestAndVerifyPointerCapture(mWindow, true);
9197
9198 // Send some relative mouse movements and receive them in the window.
9199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9200 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9201 .build());
9202 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9203 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9204
9205 // Stop pointer capture
9206 requestAndVerifyPointerCapture(mWindow, false);
9207
9208 // Continue hovering on the window
9209 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9210 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9211 .build());
9212 mWindow->consumeMotionEvent(
9213 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9214
9215 mWindow->assertNoEvents();
9216}
9217
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009218class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9219protected:
9220 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009221
9222 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9223 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9224
9225 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9226 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9227
9228 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9229 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9230 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9231 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9232 MAXIMUM_OBSCURING_OPACITY);
9233
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009234 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9235 static constexpr gui::Uid APP_B_UID{10002};
9236 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009237
9238 sp<FakeWindowHandle> mTouchWindow;
9239
9240 virtual void SetUp() override {
9241 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009242 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009243 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9244 }
9245
9246 virtual void TearDown() override {
9247 InputDispatcherTest::TearDown();
9248 mTouchWindow.clear();
9249 }
9250
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009251 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009252 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009253 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009254 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009255 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009256 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009257 return window;
9258 }
9259
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009260 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009261 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9262 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009263 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009264 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009265 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009266 return window;
9267 }
9268
9269 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009270 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9271 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9272 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009273 }
9274};
9275
9276TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009277 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009278 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009279 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009280
9281 touch();
9282
9283 mTouchWindow->assertNoEvents();
9284}
9285
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009286TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009287 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9288 const sp<FakeWindowHandle>& w =
9289 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009290 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009291
9292 touch();
9293
9294 mTouchWindow->assertNoEvents();
9295}
9296
9297TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009298 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9299 const sp<FakeWindowHandle>& w =
9300 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009301 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009302
9303 touch();
9304
9305 w->assertNoEvents();
9306}
9307
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009308TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009309 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009310 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009311
9312 touch();
9313
9314 mTouchWindow->consumeAnyMotionDown();
9315}
9316
9317TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009318 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009319 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009320 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009321 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009322
9323 touch({PointF{100, 100}});
9324
9325 mTouchWindow->consumeAnyMotionDown();
9326}
9327
9328TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009329 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009330 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009331 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009332
9333 touch();
9334
9335 mTouchWindow->consumeAnyMotionDown();
9336}
9337
9338TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9339 const sp<FakeWindowHandle>& w =
9340 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009341 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009342
9343 touch();
9344
9345 mTouchWindow->consumeAnyMotionDown();
9346}
9347
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009348TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9349 const sp<FakeWindowHandle>& w =
9350 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009351 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009352
9353 touch();
9354
9355 w->assertNoEvents();
9356}
9357
9358/**
9359 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9360 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9361 * window, the occluding window will still receive ACTION_OUTSIDE event.
9362 */
9363TEST_F(InputDispatcherUntrustedTouchesTest,
9364 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9365 const sp<FakeWindowHandle>& w =
9366 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009367 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009368 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009369
9370 touch();
9371
9372 w->consumeMotionOutside();
9373}
9374
9375TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9376 const sp<FakeWindowHandle>& w =
9377 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009378 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009379 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009380
9381 touch();
9382
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009383 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009384}
9385
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009386TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009387 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009388 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9389 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009390 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009391
9392 touch();
9393
9394 mTouchWindow->consumeAnyMotionDown();
9395}
9396
9397TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9398 const sp<FakeWindowHandle>& w =
9399 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9400 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009401 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009402
9403 touch();
9404
9405 mTouchWindow->consumeAnyMotionDown();
9406}
9407
9408TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009409 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009410 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9411 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009412 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009413
9414 touch();
9415
9416 mTouchWindow->assertNoEvents();
9417}
9418
9419TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9420 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9421 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009422 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9423 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009424 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009425 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9426 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009427 mDispatcher->onWindowInfosChanged(
9428 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009429
9430 touch();
9431
9432 mTouchWindow->assertNoEvents();
9433}
9434
9435TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9436 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9437 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009438 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9439 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009440 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009441 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9442 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009443 mDispatcher->onWindowInfosChanged(
9444 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009445
9446 touch();
9447
9448 mTouchWindow->consumeAnyMotionDown();
9449}
9450
9451TEST_F(InputDispatcherUntrustedTouchesTest,
9452 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9453 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009454 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9455 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009456 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009457 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9458 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009459 mDispatcher->onWindowInfosChanged(
9460 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009461
9462 touch();
9463
9464 mTouchWindow->consumeAnyMotionDown();
9465}
9466
9467TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9468 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009469 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9470 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009471 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009472 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9473 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009474 mDispatcher->onWindowInfosChanged(
9475 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009476
9477 touch();
9478
9479 mTouchWindow->assertNoEvents();
9480}
9481
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009482TEST_F(InputDispatcherUntrustedTouchesTest,
9483 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9484 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009485 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9486 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009487 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009488 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9489 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009490 mDispatcher->onWindowInfosChanged(
9491 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009492
9493 touch();
9494
9495 mTouchWindow->assertNoEvents();
9496}
9497
9498TEST_F(InputDispatcherUntrustedTouchesTest,
9499 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9500 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009501 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9502 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009503 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009504 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9505 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009506 mDispatcher->onWindowInfosChanged(
9507 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009508
9509 touch();
9510
9511 mTouchWindow->consumeAnyMotionDown();
9512}
9513
9514TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9515 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009516 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9517 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009518 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009519
9520 touch();
9521
9522 mTouchWindow->consumeAnyMotionDown();
9523}
9524
9525TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9526 const sp<FakeWindowHandle>& w =
9527 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009528 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009529
9530 touch();
9531
9532 mTouchWindow->consumeAnyMotionDown();
9533}
9534
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009535TEST_F(InputDispatcherUntrustedTouchesTest,
9536 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9537 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9538 const sp<FakeWindowHandle>& w =
9539 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009540 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009541
9542 touch();
9543
9544 mTouchWindow->assertNoEvents();
9545}
9546
9547TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9548 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9549 const sp<FakeWindowHandle>& w =
9550 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009551 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009552
9553 touch();
9554
9555 mTouchWindow->consumeAnyMotionDown();
9556}
9557
9558TEST_F(InputDispatcherUntrustedTouchesTest,
9559 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9560 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9561 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009562 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9563 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009564 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009565
9566 touch();
9567
9568 mTouchWindow->consumeAnyMotionDown();
9569}
9570
9571TEST_F(InputDispatcherUntrustedTouchesTest,
9572 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9573 const sp<FakeWindowHandle>& w1 =
9574 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9575 OPACITY_BELOW_THRESHOLD);
9576 const sp<FakeWindowHandle>& w2 =
9577 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9578 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009579 mDispatcher->onWindowInfosChanged(
9580 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009581
9582 touch();
9583
9584 mTouchWindow->assertNoEvents();
9585}
9586
9587/**
9588 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9589 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9590 * (which alone would result in allowing touches) does not affect the blocking behavior.
9591 */
9592TEST_F(InputDispatcherUntrustedTouchesTest,
9593 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9594 const sp<FakeWindowHandle>& wB =
9595 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9596 OPACITY_BELOW_THRESHOLD);
9597 const sp<FakeWindowHandle>& wC =
9598 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9599 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009600 mDispatcher->onWindowInfosChanged(
9601 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009602
9603 touch();
9604
9605 mTouchWindow->assertNoEvents();
9606}
9607
9608/**
9609 * This test is testing that a window from a different UID but with same application token doesn't
9610 * block the touch. Apps can share the application token for close UI collaboration for example.
9611 */
9612TEST_F(InputDispatcherUntrustedTouchesTest,
9613 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9614 const sp<FakeWindowHandle>& w =
9615 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9616 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009617 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009618
9619 touch();
9620
9621 mTouchWindow->consumeAnyMotionDown();
9622}
9623
arthurhungb89ccb02020-12-30 16:19:01 +08009624class InputDispatcherDragTests : public InputDispatcherTest {
9625protected:
9626 std::shared_ptr<FakeApplicationHandle> mApp;
9627 sp<FakeWindowHandle> mWindow;
9628 sp<FakeWindowHandle> mSecondWindow;
9629 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009630 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009631 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9632 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009633
9634 void SetUp() override {
9635 InputDispatcherTest::SetUp();
9636 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009637 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009638 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009639
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009640 mSecondWindow =
9641 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009642 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009643
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009644 mSpyWindow =
9645 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009646 mSpyWindow->setSpy(true);
9647 mSpyWindow->setTrustedOverlay(true);
9648 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9649
arthurhungb89ccb02020-12-30 16:19:01 +08009650 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009651 mDispatcher->onWindowInfosChanged(
9652 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9653 {},
9654 0,
9655 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009656 }
9657
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009658 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9659 switch (fromSource) {
9660 case AINPUT_SOURCE_TOUCHSCREEN:
9661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009662 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009663 ADISPLAY_ID_DEFAULT, {50, 50}))
9664 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9665 break;
9666 case AINPUT_SOURCE_STYLUS:
9667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009668 injectMotionEvent(*mDispatcher,
9669 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9670 AINPUT_SOURCE_STYLUS)
9671 .buttonState(
9672 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9673 .pointer(PointerBuilder(0, ToolType::STYLUS)
9674 .x(50)
9675 .y(50))
9676 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009677 break;
9678 case AINPUT_SOURCE_MOUSE:
9679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009680 injectMotionEvent(*mDispatcher,
9681 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9682 AINPUT_SOURCE_MOUSE)
9683 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9684 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9685 ToolType::MOUSE)
9686 .x(50)
9687 .y(50))
9688 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009689 break;
9690 default:
9691 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9692 }
arthurhungb89ccb02020-12-30 16:19:01 +08009693
9694 // Window should receive motion event.
9695 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009696 // Spy window should also receive motion event
9697 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009698 }
9699
9700 // Start performing drag, we will create a drag window and transfer touch to it.
9701 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9702 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009703 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009704 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009705 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009706 }
arthurhungb89ccb02020-12-30 16:19:01 +08009707
9708 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009709 mDragWindow =
9710 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009711 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009712 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9713 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9714 {},
9715 0,
9716 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009717
9718 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009719 bool transferred =
9720 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009721 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009722 if (transferred) {
9723 mWindow->consumeMotionCancel();
9724 mDragWindow->consumeMotionDown();
9725 }
9726 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009727 }
9728};
9729
9730TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009731 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009732
9733 // Move on window.
9734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009735 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009736 ADISPLAY_ID_DEFAULT, {50, 50}))
9737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9738 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9739 mWindow->consumeDragEvent(false, 50, 50);
9740 mSecondWindow->assertNoEvents();
9741
9742 // Move to another window.
9743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009744 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009745 ADISPLAY_ID_DEFAULT, {150, 50}))
9746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9747 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9748 mWindow->consumeDragEvent(true, 150, 50);
9749 mSecondWindow->consumeDragEvent(false, 50, 50);
9750
9751 // Move back to original window.
9752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009753 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009754 ADISPLAY_ID_DEFAULT, {50, 50}))
9755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9756 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9757 mWindow->consumeDragEvent(false, 50, 50);
9758 mSecondWindow->consumeDragEvent(true, -50, 50);
9759
9760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009761 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9762 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9764 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9765 mWindow->assertNoEvents();
9766 mSecondWindow->assertNoEvents();
9767}
9768
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009769TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009770 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009771
9772 // No cancel event after drag start
9773 mSpyWindow->assertNoEvents();
9774
9775 const MotionEvent secondFingerDownEvent =
9776 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009778 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9779 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009780 .build();
9781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009782 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009783 InputEventInjectionSync::WAIT_FOR_RESULT))
9784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9785
9786 // Receives cancel for first pointer after next pointer down
9787 mSpyWindow->consumeMotionCancel();
9788 mSpyWindow->consumeMotionDown();
9789
9790 mSpyWindow->assertNoEvents();
9791}
9792
arthurhungf452d0b2021-01-06 00:19:52 +08009793TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009794 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009795
9796 // Move on window.
9797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009798 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009799 ADISPLAY_ID_DEFAULT, {50, 50}))
9800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9801 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9802 mWindow->consumeDragEvent(false, 50, 50);
9803 mSecondWindow->assertNoEvents();
9804
9805 // Move to another window.
9806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009807 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009808 ADISPLAY_ID_DEFAULT, {150, 50}))
9809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9810 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9811 mWindow->consumeDragEvent(true, 150, 50);
9812 mSecondWindow->consumeDragEvent(false, 50, 50);
9813
9814 // drop to another window.
9815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009816 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009817 {150, 50}))
9818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9819 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009820 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009821 mWindow->assertNoEvents();
9822 mSecondWindow->assertNoEvents();
9823}
9824
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009825TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9826 startDrag();
9827
9828 // No cancel event after drag start
9829 mSpyWindow->assertNoEvents();
9830
9831 const MotionEvent secondFingerDownEvent =
9832 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9833 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9834 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9835 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9836 .build();
9837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9838 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9839 InputEventInjectionSync::WAIT_FOR_RESULT))
9840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9841
9842 // Receives cancel for first pointer after next pointer down
9843 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08009844 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009845 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9846
9847 mSpyWindow->assertNoEvents();
9848
9849 // Spy window calls pilfer pointers
9850 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9851 mDragWindow->assertNoEvents();
9852
9853 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009854 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009855 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9856 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9857 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9858 .build();
9859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009860 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009861 InputEventInjectionSync::WAIT_FOR_RESULT))
9862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9863
9864 // Drag window should still receive the new event
9865 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9866 mDragWindow->assertNoEvents();
9867}
9868
arthurhung6d4bed92021-03-17 11:59:33 +08009869TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009870 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009871
9872 // Move on window and keep button pressed.
9873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009874 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009875 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9876 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009877 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009878 .build()))
9879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9880 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9881 mWindow->consumeDragEvent(false, 50, 50);
9882 mSecondWindow->assertNoEvents();
9883
9884 // Move to another window and release button, expect to drop item.
9885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009886 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009887 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9888 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009889 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009890 .build()))
9891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9892 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9893 mWindow->assertNoEvents();
9894 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009895 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009896
9897 // nothing to the window.
9898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009899 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009900 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9901 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009902 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009903 .build()))
9904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9905 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9906 mWindow->assertNoEvents();
9907 mSecondWindow->assertNoEvents();
9908}
9909
Arthur Hung54745652022-04-20 07:17:41 +00009910TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009911 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08009912
9913 // Set second window invisible.
9914 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009915 mDispatcher->onWindowInfosChanged(
9916 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +08009917
9918 // Move on window.
9919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009920 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009921 ADISPLAY_ID_DEFAULT, {50, 50}))
9922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9923 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9924 mWindow->consumeDragEvent(false, 50, 50);
9925 mSecondWindow->assertNoEvents();
9926
9927 // Move to another window.
9928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009929 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009930 ADISPLAY_ID_DEFAULT, {150, 50}))
9931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9932 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9933 mWindow->consumeDragEvent(true, 150, 50);
9934 mSecondWindow->assertNoEvents();
9935
9936 // drop to another window.
9937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009938 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +08009939 {150, 50}))
9940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9941 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009942 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08009943 mWindow->assertNoEvents();
9944 mSecondWindow->assertNoEvents();
9945}
9946
Arthur Hung54745652022-04-20 07:17:41 +00009947TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009948 // Ensure window could track pointerIds if it didn't support split touch.
9949 mWindow->setPreventSplitting(true);
9950
Arthur Hung54745652022-04-20 07:17:41 +00009951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009952 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009953 {50, 50}))
9954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9955 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9956
9957 const MotionEvent secondFingerDownEvent =
9958 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9959 .displayId(ADISPLAY_ID_DEFAULT)
9960 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009961 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9962 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009963 .build();
9964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009965 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009966 InputEventInjectionSync::WAIT_FOR_RESULT))
9967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009968 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00009969
9970 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009971 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009972}
9973
9974TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
9975 // First down on second window.
9976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009977 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +00009978 {150, 50}))
9979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9980
9981 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9982
9983 // Second down on first window.
9984 const MotionEvent secondFingerDownEvent =
9985 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9986 .displayId(ADISPLAY_ID_DEFAULT)
9987 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009988 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
9989 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00009990 .build();
9991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009992 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +00009993 InputEventInjectionSync::WAIT_FOR_RESULT))
9994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9995 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9996
9997 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009998 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00009999
10000 // Move on window.
10001 const MotionEvent secondFingerMoveEvent =
10002 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10003 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010004 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10005 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010006 .build();
10007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010008 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010009 InputEventInjectionSync::WAIT_FOR_RESULT));
10010 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10011 mWindow->consumeDragEvent(false, 50, 50);
10012 mSecondWindow->consumeMotionMove();
10013
10014 // Release the drag pointer should perform drop.
10015 const MotionEvent secondFingerUpEvent =
10016 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10017 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010018 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10019 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010020 .build();
10021 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010022 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010023 InputEventInjectionSync::WAIT_FOR_RESULT));
10024 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010025 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010026 mWindow->assertNoEvents();
10027 mSecondWindow->consumeMotionMove();
10028}
10029
Arthur Hung3915c1f2022-05-31 07:17:17 +000010030TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010031 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010032
10033 // Update window of second display.
10034 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010035 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010036 mDispatcher->onWindowInfosChanged(
10037 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10038 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10039 {},
10040 0,
10041 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010042
10043 // Let second display has a touch state.
10044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010045 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010046 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10047 AINPUT_SOURCE_TOUCHSCREEN)
10048 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010049 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010050 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010051 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010052 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010053 mDispatcher->onWindowInfosChanged(
10054 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10055 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10056 {},
10057 0,
10058 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010059
10060 // Move on window.
10061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010062 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010063 ADISPLAY_ID_DEFAULT, {50, 50}))
10064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10065 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10066 mWindow->consumeDragEvent(false, 50, 50);
10067 mSecondWindow->assertNoEvents();
10068
10069 // Move to another window.
10070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010071 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010072 ADISPLAY_ID_DEFAULT, {150, 50}))
10073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10074 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10075 mWindow->consumeDragEvent(true, 150, 50);
10076 mSecondWindow->consumeDragEvent(false, 50, 50);
10077
10078 // drop to another window.
10079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010080 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010081 {150, 50}))
10082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10083 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010084 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010085 mWindow->assertNoEvents();
10086 mSecondWindow->assertNoEvents();
10087}
10088
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010089TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10090 startDrag(true, AINPUT_SOURCE_MOUSE);
10091 // Move on window.
10092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010093 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010094 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10095 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010096 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010097 .x(50)
10098 .y(50))
10099 .build()))
10100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10101 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10102 mWindow->consumeDragEvent(false, 50, 50);
10103 mSecondWindow->assertNoEvents();
10104
10105 // Move to another window.
10106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010107 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010108 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10109 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010110 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010111 .x(150)
10112 .y(50))
10113 .build()))
10114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10115 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10116 mWindow->consumeDragEvent(true, 150, 50);
10117 mSecondWindow->consumeDragEvent(false, 50, 50);
10118
10119 // drop to another window.
10120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010121 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010122 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10123 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010124 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010125 .x(150)
10126 .y(50))
10127 .build()))
10128 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10129 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010130 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010131 mWindow->assertNoEvents();
10132 mSecondWindow->assertNoEvents();
10133}
10134
Linnan Li5af92f92023-07-14 14:36:22 +080010135/**
10136 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10137 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10138 */
10139TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10140 // Down on second window
10141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10142 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10143 {150, 50}))
10144 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10145
10146 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10147 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10148
10149 // Down on first window
10150 const MotionEvent secondFingerDownEvent =
10151 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10152 .displayId(ADISPLAY_ID_DEFAULT)
10153 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10154 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10155 .build();
10156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10157 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10158 InputEventInjectionSync::WAIT_FOR_RESULT))
10159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10160 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10161 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10162 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10163
10164 // Start drag on first window
10165 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10166
10167 // Trigger cancel
10168 mDispatcher->cancelCurrentTouch();
10169 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10170 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10171 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10172
10173 ASSERT_TRUE(mDispatcher->waitForIdle());
10174 // The D&D finished with nullptr
10175 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10176
10177 // Remove drag window
10178 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10179
10180 // Inject a simple gesture, ensure dispatcher not crashed
10181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10182 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10183 PointF{50, 50}))
10184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10185 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10186
10187 const MotionEvent moveEvent =
10188 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10189 .displayId(ADISPLAY_ID_DEFAULT)
10190 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10191 .build();
10192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10193 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10194 InputEventInjectionSync::WAIT_FOR_RESULT))
10195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10196 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10197
10198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10199 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10200 {50, 50}))
10201 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10202 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10203}
10204
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010205TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10206 // Start hovering over the window.
10207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10208 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10209 ADISPLAY_ID_DEFAULT, {50, 50}));
10210
10211 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10212 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10213
10214 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10215 << "Drag and drop should not work with a hovering pointer";
10216}
10217
Vishnu Nair062a8672021-09-03 16:07:44 -070010218class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10219
10220TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010222 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10223 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010224 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10226 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010227 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010228 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010229 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010230
10231 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010232 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010233 window->assertNoEvents();
10234
Prabir Pradhan678438e2023-04-13 19:32:51 +000010235 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10236 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010237 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10238 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010239 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010240 window->assertNoEvents();
10241
10242 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010243 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010244 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010245
Prabir Pradhan678438e2023-04-13 19:32:51 +000010246 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010247 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10248
Prabir Pradhan678438e2023-04-13 19:32:51 +000010249 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10250 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010251 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10252 window->assertNoEvents();
10253}
10254
10255TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10256 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10257 std::make_shared<FakeApplicationHandle>();
10258 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010259 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10260 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010261 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010262 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010263 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010264 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010265 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10266 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010267 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010268 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010269 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10270 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010271 mDispatcher->onWindowInfosChanged(
10272 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010273 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010274 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010275
10276 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010277 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010278 window->assertNoEvents();
10279
Prabir Pradhan678438e2023-04-13 19:32:51 +000010280 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10281 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010282 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10283 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010284 window->assertNoEvents();
10285
10286 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010287 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010288 mDispatcher->onWindowInfosChanged(
10289 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010290
Prabir Pradhan678438e2023-04-13 19:32:51 +000010291 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010292 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10293
Prabir Pradhan678438e2023-04-13 19:32:51 +000010294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10295 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010296 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10297 window->assertNoEvents();
10298}
10299
10300TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10301 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10302 std::make_shared<FakeApplicationHandle>();
10303 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010304 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10305 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010306 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010307 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010308 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010309 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010310 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10311 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010312 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010313 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010314 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10315 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010316 mDispatcher->onWindowInfosChanged(
10317 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010318 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010319 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010320
10321 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010322 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010323 window->assertNoEvents();
10324
Prabir Pradhan678438e2023-04-13 19:32:51 +000010325 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10326 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010327 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10328 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010329 window->assertNoEvents();
10330
10331 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010332 mDispatcher->onWindowInfosChanged(
10333 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010334
Prabir Pradhan678438e2023-04-13 19:32:51 +000010335 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010336 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10337
Prabir Pradhan678438e2023-04-13 19:32:51 +000010338 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10339 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010340 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10341 window->assertNoEvents();
10342}
10343
Antonio Kantekf16f2832021-09-28 04:39:20 +000010344class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10345protected:
10346 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010347 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010348 sp<FakeWindowHandle> mWindow;
10349 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010350 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010351
10352 void SetUp() override {
10353 InputDispatcherTest::SetUp();
10354
10355 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010356 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010357 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010358 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010359 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010360 mSecondWindow =
10361 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010362 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010363 mThirdWindow =
10364 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10365 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10366 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010367
10368 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010369 mDispatcher->onWindowInfosChanged(
10370 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10371 {},
10372 0,
10373 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010374 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010375 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010376
Antonio Kantek15beb512022-06-13 22:35:41 +000010377 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010378 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010379 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010380 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10381 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010382 mThirdWindow->assertNoEvents();
10383 }
10384
10385 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10386 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010387 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010388 SECOND_DISPLAY_ID)) {
10389 mWindow->assertNoEvents();
10390 mSecondWindow->assertNoEvents();
10391 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010392 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010393 }
10394
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010395 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010396 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010397 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10398 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010399 mWindow->consumeTouchModeEvent(inTouchMode);
10400 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010401 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010402 }
10403};
10404
Antonio Kantek26defcf2022-02-08 01:12:27 +000010405TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010406 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010407 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10408 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010409 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010410}
10411
Antonio Kantek26defcf2022-02-08 01:12:27 +000010412TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10413 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010414 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010415 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010416 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010417 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010418 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010419 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010420 mWindow->assertNoEvents();
10421 mSecondWindow->assertNoEvents();
10422}
10423
10424TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10425 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010426 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010427 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010428 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010429 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010430 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010431}
10432
Antonio Kantekf16f2832021-09-28 04:39:20 +000010433TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010434 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010435 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10436 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010437 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010438 mWindow->assertNoEvents();
10439 mSecondWindow->assertNoEvents();
10440}
10441
Antonio Kantek15beb512022-06-13 22:35:41 +000010442TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10443 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10444 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10445 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010446 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010447 mWindow->assertNoEvents();
10448 mSecondWindow->assertNoEvents();
10449 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10450}
10451
Antonio Kantek48710e42022-03-24 14:19:30 -070010452TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10453 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10455 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010456 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10457 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10458
10459 // Then remove focus.
10460 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010461 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010462
10463 // Assert that caller can switch touch mode by owning one of the last interacted window.
10464 const WindowInfo& windowInfo = *mWindow->getInfo();
10465 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10466 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010467 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010468}
10469
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010470class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10471public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010472 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010473 std::shared_ptr<FakeApplicationHandle> application =
10474 std::make_shared<FakeApplicationHandle>();
10475 std::string name = "Fake Spy ";
10476 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010477 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10478 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010479 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010480 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010481 return spy;
10482 }
10483
10484 sp<FakeWindowHandle> createForeground() {
10485 std::shared_ptr<FakeApplicationHandle> application =
10486 std::make_shared<FakeApplicationHandle>();
10487 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010488 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10489 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010490 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010491 return window;
10492 }
10493
10494private:
10495 int mSpyCount{0};
10496};
10497
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010498using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010499/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010500 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10501 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010502TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010503 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010504 ScopedSilentDeath _silentDeath;
10505
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010506 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010507 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010508 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010509 ".* not a trusted overlay");
10510}
10511
10512/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010513 * Input injection into a display with a spy window but no foreground windows should succeed.
10514 */
10515TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010516 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010517 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010518
10519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010520 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10522 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10523}
10524
10525/**
10526 * Verify the order in which different input windows receive events. The touched foreground window
10527 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10528 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10529 * receive events before ones belows it.
10530 *
10531 * Here, we set up a scenario with four windows in the following Z order from the top:
10532 * spy1, spy2, window, spy3.
10533 * We then inject an event and verify that the foreground "window" receives it first, followed by
10534 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10535 * window.
10536 */
10537TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10538 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010539 auto spy1 = createSpy();
10540 auto spy2 = createSpy();
10541 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010542 mDispatcher->onWindowInfosChanged(
10543 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010544 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10545 const size_t numChannels = channels.size();
10546
Michael Wright8e9a8562022-02-09 13:44:29 +000010547 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010548 if (!epollFd.ok()) {
10549 FAIL() << "Failed to create epoll fd";
10550 }
10551
10552 for (size_t i = 0; i < numChannels; i++) {
10553 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10554 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10555 FAIL() << "Failed to add fd to epoll";
10556 }
10557 }
10558
10559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010560 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010561 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10562
10563 std::vector<size_t> eventOrder;
10564 std::vector<struct epoll_event> events(numChannels);
10565 for (;;) {
10566 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10567 (100ms).count());
10568 if (nFds < 0) {
10569 FAIL() << "Failed to call epoll_wait";
10570 }
10571 if (nFds == 0) {
10572 break; // epoll_wait timed out
10573 }
10574 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010575 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010576 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010577 channels[i]->consumeMotionDown();
10578 }
10579 }
10580
10581 // Verify the order in which the events were received.
10582 EXPECT_EQ(3u, eventOrder.size());
10583 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10584 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10585 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10586}
10587
10588/**
10589 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10590 */
10591TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10592 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010593 auto spy = createSpy();
10594 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010595 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010596
10597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010598 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010599 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10600 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10601 spy->assertNoEvents();
10602}
10603
10604/**
10605 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10606 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10607 * to the window.
10608 */
10609TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10610 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010611 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010612 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010613 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010614
10615 // Inject an event outside the spy window's touchable region.
10616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010617 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10619 window->consumeMotionDown();
10620 spy->assertNoEvents();
10621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010622 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10624 window->consumeMotionUp();
10625 spy->assertNoEvents();
10626
10627 // Inject an event inside the spy window's touchable region.
10628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010629 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010630 {5, 10}))
10631 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10632 window->consumeMotionDown();
10633 spy->consumeMotionDown();
10634}
10635
10636/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010637 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010638 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010639 */
10640TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10641 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010642 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010643 auto spy = createSpy();
10644 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010645 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010646 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010647 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010648
10649 // Inject an event outside the spy window's frame and touchable region.
10650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010652 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10654 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010655 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010656}
10657
10658/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010659 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10660 * pointers that are down within its bounds.
10661 */
10662TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10663 auto windowLeft = createForeground();
10664 windowLeft->setFrame({0, 0, 100, 200});
10665 auto windowRight = createForeground();
10666 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010667 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010668 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010669 mDispatcher->onWindowInfosChanged(
10670 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010671
10672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010673 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010674 {50, 50}))
10675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10676 windowLeft->consumeMotionDown();
10677 spy->consumeMotionDown();
10678
10679 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010680 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010681 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010682 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10683 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010684 .build();
10685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010686 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010687 InputEventInjectionSync::WAIT_FOR_RESULT))
10688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10689 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010690 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010691}
10692
10693/**
10694 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10695 * the spy should receive the second pointer with ACTION_DOWN.
10696 */
10697TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10698 auto window = createForeground();
10699 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010700 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010701 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010702 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010703
10704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010705 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010706 {50, 50}))
10707 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10708 window->consumeMotionDown();
10709 spyRight->assertNoEvents();
10710
10711 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010712 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010713 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010714 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10715 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010716 .build();
10717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010718 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010719 InputEventInjectionSync::WAIT_FOR_RESULT))
10720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010721 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010722 spyRight->consumeMotionDown();
10723}
10724
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010725/**
10726 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10727 * windows should be allowed to control split touch.
10728 */
10729TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010730 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010731 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010732 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010733 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010734
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010735 auto window = createForeground();
10736 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010737
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010738 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010739
10740 // First finger down, no window touched.
10741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010742 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010743 {100, 200}))
10744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10745 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10746 window->assertNoEvents();
10747
10748 // Second finger down on window, the window should receive touch down.
10749 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010750 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010751 .displayId(ADISPLAY_ID_DEFAULT)
10752 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010753 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10754 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010755 .build();
10756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010757 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010758 InputEventInjectionSync::WAIT_FOR_RESULT))
10759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10760
10761 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010762 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010763}
10764
10765/**
10766 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10767 * do not receive key events.
10768 */
10769TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010770 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010771 spy->setFocusable(false);
10772
10773 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010774 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010775 setFocusedWindow(window);
10776 window->consumeFocusEvent(true);
10777
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010779 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10780 window->consumeKeyDown(ADISPLAY_ID_NONE);
10781
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010783 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10784 window->consumeKeyUp(ADISPLAY_ID_NONE);
10785
10786 spy->assertNoEvents();
10787}
10788
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010789using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10790
10791/**
10792 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10793 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10794 */
10795TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10796 auto window = createForeground();
10797 auto spy1 = createSpy();
10798 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010799 mDispatcher->onWindowInfosChanged(
10800 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010801
10802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010803 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10805 window->consumeMotionDown();
10806 spy1->consumeMotionDown();
10807 spy2->consumeMotionDown();
10808
10809 // Pilfer pointers from the second spy window.
10810 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10811 spy2->assertNoEvents();
10812 spy1->consumeMotionCancel();
10813 window->consumeMotionCancel();
10814
10815 // The rest of the gesture should only be sent to the second spy window.
10816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010817 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010818 ADISPLAY_ID_DEFAULT))
10819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10820 spy2->consumeMotionMove();
10821 spy1->assertNoEvents();
10822 window->assertNoEvents();
10823}
10824
10825/**
10826 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10827 * in the middle of the gesture.
10828 */
10829TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10830 auto window = createForeground();
10831 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010832 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010833
10834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10837 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10838 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10839
10840 window->releaseChannel();
10841
10842 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10843
10844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010845 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10847 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10848}
10849
10850/**
10851 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10852 * the spy, but not to any other windows.
10853 */
10854TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10855 auto spy = createSpy();
10856 auto window = createForeground();
10857
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010858 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010859
10860 // First finger down on the window and the spy.
10861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010862 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010863 {100, 200}))
10864 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10865 spy->consumeMotionDown();
10866 window->consumeMotionDown();
10867
10868 // Spy window pilfers the pointers.
10869 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10870 window->consumeMotionCancel();
10871
10872 // Second finger down on the window and spy, but the window should not receive the pointer down.
10873 const MotionEvent secondFingerDownEvent =
10874 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10875 .displayId(ADISPLAY_ID_DEFAULT)
10876 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010877 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10878 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010879 .build();
10880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010881 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010882 InputEventInjectionSync::WAIT_FOR_RESULT))
10883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10884
Harry Cutts33476232023-01-30 19:57:29 +000010885 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010886
10887 // Third finger goes down outside all windows, so injection should fail.
10888 const MotionEvent thirdFingerDownEvent =
10889 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10890 .displayId(ADISPLAY_ID_DEFAULT)
10891 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010892 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10893 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10894 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010895 .build();
10896 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010897 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010898 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010899 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010900
10901 spy->assertNoEvents();
10902 window->assertNoEvents();
10903}
10904
10905/**
10906 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
10907 */
10908TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
10909 auto spy = createSpy();
10910 spy->setFrame(Rect(0, 0, 100, 100));
10911 auto window = createForeground();
10912 window->setFrame(Rect(0, 0, 200, 200));
10913
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010914 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010915
10916 // First finger down on the window only
10917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010918 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010919 {150, 150}))
10920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10921 window->consumeMotionDown();
10922
10923 // Second finger down on the spy and window
10924 const MotionEvent secondFingerDownEvent =
10925 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10926 .displayId(ADISPLAY_ID_DEFAULT)
10927 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010928 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10929 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010930 .build();
10931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010932 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010933 InputEventInjectionSync::WAIT_FOR_RESULT))
10934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10935 spy->consumeMotionDown();
10936 window->consumeMotionPointerDown(1);
10937
10938 // Third finger down on the spy and window
10939 const MotionEvent thirdFingerDownEvent =
10940 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10941 .displayId(ADISPLAY_ID_DEFAULT)
10942 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010943 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
10944 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
10945 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010946 .build();
10947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010948 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010949 InputEventInjectionSync::WAIT_FOR_RESULT))
10950 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10951 spy->consumeMotionPointerDown(1);
10952 window->consumeMotionPointerDown(2);
10953
10954 // Spy window pilfers the pointers.
10955 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000010956 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
10957 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010958
10959 spy->assertNoEvents();
10960 window->assertNoEvents();
10961}
10962
10963/**
10964 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
10965 * other windows should be canceled. If this results in the cancellation of all pointers for some
10966 * window, then that window should receive ACTION_CANCEL.
10967 */
10968TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
10969 auto spy = createSpy();
10970 spy->setFrame(Rect(0, 0, 100, 100));
10971 auto window = createForeground();
10972 window->setFrame(Rect(0, 0, 200, 200));
10973
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010974 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010975
10976 // First finger down on both spy and window
10977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010979 {10, 10}))
10980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10981 window->consumeMotionDown();
10982 spy->consumeMotionDown();
10983
10984 // Second finger down on the spy and window
10985 const MotionEvent secondFingerDownEvent =
10986 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10987 .displayId(ADISPLAY_ID_DEFAULT)
10988 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010989 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
10990 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010991 .build();
10992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010993 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010994 InputEventInjectionSync::WAIT_FOR_RESULT))
10995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10996 spy->consumeMotionPointerDown(1);
10997 window->consumeMotionPointerDown(1);
10998
10999 // Spy window pilfers the pointers.
11000 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11001 window->consumeMotionCancel();
11002
11003 spy->assertNoEvents();
11004 window->assertNoEvents();
11005}
11006
11007/**
11008 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11009 * be sent to other windows
11010 */
11011TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11012 auto spy = createSpy();
11013 spy->setFrame(Rect(0, 0, 100, 100));
11014 auto window = createForeground();
11015 window->setFrame(Rect(0, 0, 200, 200));
11016
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011017 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011018
11019 // First finger down on both window and spy
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 {10, 10}))
11023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11024 window->consumeMotionDown();
11025 spy->consumeMotionDown();
11026
11027 // Spy window pilfers the pointers.
11028 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11029 window->consumeMotionCancel();
11030
11031 // Second finger down on the window only
11032 const MotionEvent secondFingerDownEvent =
11033 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11034 .displayId(ADISPLAY_ID_DEFAULT)
11035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011038 .build();
11039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011040 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011041 InputEventInjectionSync::WAIT_FOR_RESULT))
11042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11043 window->consumeMotionDown();
11044 window->assertNoEvents();
11045
11046 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11047 spy->consumeMotionMove();
11048 spy->assertNoEvents();
11049}
11050
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011051/**
11052 * A window on the left and a window on the right. Also, a spy window that's above all of the
11053 * windows, and spanning both left and right windows.
11054 * Send simultaneous motion streams from two different devices, one to the left window, and another
11055 * to the right window.
11056 * Pilfer from spy window.
11057 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11058 */
11059TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11060 sp<FakeWindowHandle> spy = createSpy();
11061 spy->setFrame(Rect(0, 0, 200, 200));
11062 sp<FakeWindowHandle> leftWindow = createForeground();
11063 leftWindow->setFrame(Rect(0, 0, 100, 100));
11064
11065 sp<FakeWindowHandle> rightWindow = createForeground();
11066 rightWindow->setFrame(Rect(100, 0, 200, 100));
11067
11068 constexpr int32_t stylusDeviceId = 1;
11069 constexpr int32_t touchDeviceId = 2;
11070
11071 mDispatcher->onWindowInfosChanged(
11072 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11073
11074 // Stylus down on left window and spy
11075 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11076 .deviceId(stylusDeviceId)
11077 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11078 .build());
11079 leftWindow->consumeMotionEvent(
11080 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11081 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11082
11083 // Finger down on right window and spy - but spy already has stylus
11084 mDispatcher->notifyMotion(
11085 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11086 .deviceId(touchDeviceId)
11087 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11088 .build());
11089 rightWindow->consumeMotionEvent(
11090 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011091 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011092
11093 // Act: pilfer from spy. Spy is currently receiving touch events.
11094 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011095 leftWindow->consumeMotionEvent(
11096 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011097 rightWindow->consumeMotionEvent(
11098 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11099
11100 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11101 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11102 .deviceId(stylusDeviceId)
11103 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11104 .build());
11105 mDispatcher->notifyMotion(
11106 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11107 .deviceId(touchDeviceId)
11108 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11109 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011110 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011111
11112 spy->assertNoEvents();
11113 leftWindow->assertNoEvents();
11114 rightWindow->assertNoEvents();
11115}
11116
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011117TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11118 auto window = createForeground();
11119 auto spy = createSpy();
11120 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11121
11122 mDispatcher->notifyMotion(
11123 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11124 .deviceId(1)
11125 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11126 .build());
11127 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11128 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11129
11130 // Pilfer pointers from the spy window should fail.
11131 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11132 spy->assertNoEvents();
11133 window->assertNoEvents();
11134}
11135
Prabir Pradhand65552b2021-10-07 11:23:50 -070011136class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11137public:
11138 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11139 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11140 std::make_shared<FakeApplicationHandle>();
11141 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011142 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11143 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011144 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011145 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011146 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011147 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011148 overlay->setTrustedOverlay(true);
11149
11150 std::shared_ptr<FakeApplicationHandle> application =
11151 std::make_shared<FakeApplicationHandle>();
11152 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011153 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11154 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011155 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011156 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011157
11158 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011159 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011160 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011161 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011162 return {std::move(overlay), std::move(window)};
11163 }
11164
11165 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011166 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011167 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011168 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011169 }
11170
11171 void sendStylusEvent(int32_t action) {
11172 NotifyMotionArgs motionArgs =
11173 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11174 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011175 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011176 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011177 }
11178};
11179
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011180using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11181
11182TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011183 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011184 ScopedSilentDeath _silentDeath;
11185
Prabir Pradhand65552b2021-10-07 11:23:50 -070011186 auto [overlay, window] = setupStylusOverlayScenario();
11187 overlay->setTrustedOverlay(false);
11188 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011189 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11190 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011191 ".* not a trusted overlay");
11192}
11193
11194TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11195 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011196 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011197
11198 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11199 overlay->consumeMotionDown();
11200 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11201 overlay->consumeMotionUp();
11202
11203 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11204 window->consumeMotionDown();
11205 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11206 window->consumeMotionUp();
11207
11208 overlay->assertNoEvents();
11209 window->assertNoEvents();
11210}
11211
11212TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11213 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011214 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011215 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011216
11217 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11218 overlay->consumeMotionDown();
11219 window->consumeMotionDown();
11220 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11221 overlay->consumeMotionUp();
11222 window->consumeMotionUp();
11223
11224 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11225 window->consumeMotionDown();
11226 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11227 window->consumeMotionUp();
11228
11229 overlay->assertNoEvents();
11230 window->assertNoEvents();
11231}
11232
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011233/**
11234 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11235 * The scenario is as follows:
11236 * - The stylus interceptor overlay is configured as a spy window.
11237 * - The stylus interceptor spy receives the start of a new stylus gesture.
11238 * - It pilfers pointers and then configures itself to no longer be a spy.
11239 * - The stylus interceptor continues to receive the rest of the gesture.
11240 */
11241TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11242 auto [overlay, window] = setupStylusOverlayScenario();
11243 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011244 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011245
11246 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11247 overlay->consumeMotionDown();
11248 window->consumeMotionDown();
11249
11250 // The interceptor pilfers the pointers.
11251 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11252 window->consumeMotionCancel();
11253
11254 // The interceptor configures itself so that it is no longer a spy.
11255 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011256 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011257
11258 // It continues to receive the rest of the stylus gesture.
11259 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11260 overlay->consumeMotionMove();
11261 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11262 overlay->consumeMotionUp();
11263
11264 window->assertNoEvents();
11265}
11266
Prabir Pradhan5735a322022-04-11 17:23:34 +000011267struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011268 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011269 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011270 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11271 std::unique_ptr<InputDispatcher>& mDispatcher;
11272
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011273 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011274 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11275
11276 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011277 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011278 ADISPLAY_ID_DEFAULT, {100, 200},
11279 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11280 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11281 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11282 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11283 }
11284
11285 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011286 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011287 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011288 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011289 mPolicyFlags);
11290 }
11291
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011292 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011293 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11294 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011295 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11296 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011297 window->setOwnerInfo(mPid, mUid);
11298 return window;
11299 }
11300};
11301
11302using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11303
11304TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011305 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011306 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011307 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011308
11309 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11310 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11311 window->consumeMotionDown();
11312
11313 setFocusedWindow(window);
11314 window->consumeFocusEvent(true);
11315
11316 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11317 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11318 window->consumeKeyDown(ADISPLAY_ID_NONE);
11319}
11320
11321TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011322 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011323 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011324 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011325
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011326 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011327 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11328 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11329
11330 setFocusedWindow(window);
11331 window->consumeFocusEvent(true);
11332
11333 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11334 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11335 window->assertNoEvents();
11336}
11337
11338TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011339 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011340 auto window = owner.createWindow("Owned window");
11341 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011342 spy->setSpy(true);
11343 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011344 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011345
11346 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11347 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11348 spy->consumeMotionDown();
11349 window->consumeMotionDown();
11350}
11351
11352TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011353 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011354 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011355
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011356 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011357 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011358 randosSpy->setSpy(true);
11359 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011360 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011361
11362 // The event is targeted at owner's window, so injection should succeed, but the spy should
11363 // not receive the event.
11364 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11365 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11366 randosSpy->assertNoEvents();
11367 window->consumeMotionDown();
11368}
11369
11370TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011371 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011372 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011373
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011374 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011375 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011376 randosSpy->setSpy(true);
11377 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011378 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011379
11380 // A user that has injection permission can inject into any window.
11381 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011382 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011383 ADISPLAY_ID_DEFAULT));
11384 randosSpy->consumeMotionDown();
11385 window->consumeMotionDown();
11386
11387 setFocusedWindow(randosSpy);
11388 randosSpy->consumeFocusEvent(true);
11389
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011390 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011391 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11392 window->assertNoEvents();
11393}
11394
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011395TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011396 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011397 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011398
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011399 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011400 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011401 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11402 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011403 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011404
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011405 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011406 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11407 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11408 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011409 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011410}
11411
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011412using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11413
11414TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11416
11417 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11418 ADISPLAY_ID_DEFAULT);
11419 left->setFrame(Rect(0, 0, 100, 100));
11420 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11421 "Right Window", ADISPLAY_ID_DEFAULT);
11422 right->setFrame(Rect(100, 0, 200, 100));
11423 sp<FakeWindowHandle> spy =
11424 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11425 spy->setFrame(Rect(0, 0, 200, 100));
11426 spy->setTrustedOverlay(true);
11427 spy->setSpy(true);
11428
11429 mDispatcher->onWindowInfosChanged(
11430 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11431
11432 // Hover into the left window.
11433 mDispatcher->notifyMotion(
11434 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11435 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11436 .build());
11437
11438 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11439 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11440
11441 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11442 /*pointerId=*/0));
11443 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11444 /*pointerId=*/0));
11445 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11446 /*pointerId=*/0));
11447
11448 // Hover move to the right window.
11449 mDispatcher->notifyMotion(
11450 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11451 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11452 .build());
11453
11454 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11455 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11456 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11457
11458 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11459 /*pointerId=*/0));
11460 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11461 /*pointerId=*/0));
11462 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11463 /*pointerId=*/0));
11464
11465 // Stop hovering.
11466 mDispatcher->notifyMotion(
11467 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11468 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11469 .build());
11470
11471 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11472 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11473
11474 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11475 /*pointerId=*/0));
11476 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11477 /*pointerId=*/0));
11478 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11479 /*pointerId=*/0));
11480}
11481
11482TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11483 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11484
11485 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11486 ADISPLAY_ID_DEFAULT);
11487 left->setFrame(Rect(0, 0, 100, 100));
11488 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11489 "Right Window", ADISPLAY_ID_DEFAULT);
11490 right->setFrame(Rect(100, 0, 200, 100));
11491 sp<FakeWindowHandle> spy =
11492 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11493 spy->setFrame(Rect(0, 0, 200, 100));
11494 spy->setTrustedOverlay(true);
11495 spy->setSpy(true);
11496
11497 mDispatcher->onWindowInfosChanged(
11498 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11499
11500 // First pointer down on left window.
11501 mDispatcher->notifyMotion(
11502 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11503 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11504 .build());
11505
11506 left->consumeMotionDown();
11507 spy->consumeMotionDown();
11508
11509 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11510 /*pointerId=*/0));
11511 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11512 /*pointerId=*/0));
11513 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11514 /*pointerId=*/0));
11515
11516 // Second pointer down on right window.
11517 mDispatcher->notifyMotion(
11518 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11519 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11520 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11521 .build());
11522
11523 left->consumeMotionMove();
11524 right->consumeMotionDown();
11525 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11526
11527 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11528 /*pointerId=*/0));
11529 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11530 /*pointerId=*/0));
11531 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11532 /*pointerId=*/0));
11533 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11534 /*pointerId=*/1));
11535 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11536 /*pointerId=*/1));
11537 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11538 /*pointerId=*/1));
11539
11540 // Second pointer up.
11541 mDispatcher->notifyMotion(
11542 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11543 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11544 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11545 .build());
11546
11547 left->consumeMotionMove();
11548 right->consumeMotionUp();
11549 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11550
11551 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11552 /*pointerId=*/0));
11553 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11554 /*pointerId=*/0));
11555 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11556 /*pointerId=*/0));
11557 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11558 /*pointerId=*/1));
11559 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11560 /*pointerId=*/1));
11561 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11562 /*pointerId=*/1));
11563
11564 // First pointer up.
11565 mDispatcher->notifyMotion(
11566 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11567 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11568 .build());
11569
11570 left->consumeMotionUp();
11571 spy->consumeMotionUp();
11572
11573 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11574 /*pointerId=*/0));
11575 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11576 /*pointerId=*/0));
11577 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11578 /*pointerId=*/0));
11579}
11580
11581TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11583
11584 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11585 ADISPLAY_ID_DEFAULT);
11586 left->setFrame(Rect(0, 0, 100, 100));
11587 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11588 "Right Window", ADISPLAY_ID_DEFAULT);
11589 right->setFrame(Rect(100, 0, 200, 100));
11590
11591 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11592
11593 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11594 /*pointerId=*/0));
11595 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11596 /*pointerId=*/0));
11597
11598 // Hover move into the window.
11599 mDispatcher->notifyMotion(
11600 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11601 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11602 .rawXCursorPosition(50)
11603 .rawYCursorPosition(50)
11604 .deviceId(DEVICE_ID)
11605 .build());
11606
11607 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11608
11609 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11610 /*pointerId=*/0));
11611
11612 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11613 mDispatcher->notifyMotion(
11614 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11615 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11616 .rawXCursorPosition(51)
11617 .rawYCursorPosition(50)
11618 .deviceId(SECOND_DEVICE_ID)
11619 .build());
11620
11621 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11622 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11623
11624 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11625 // a HOVER_EXIT from the first device.
11626 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11627 /*pointerId=*/0));
11628 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11629 SECOND_DEVICE_ID,
11630 /*pointerId=*/0));
11631
11632 // Move the mouse outside the window. Document the current behavior, where the window does not
11633 // receive HOVER_EXIT even though the mouse left the window.
11634 mDispatcher->notifyMotion(
11635 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11636 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11637 .rawXCursorPosition(150)
11638 .rawYCursorPosition(50)
11639 .deviceId(SECOND_DEVICE_ID)
11640 .build());
11641
11642 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11643 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11644 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11645 /*pointerId=*/0));
11646 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11647 SECOND_DEVICE_ID,
11648 /*pointerId=*/0));
11649}
11650
Garfield Tane84e6f92019-08-29 17:28:41 -070011651} // namespace android::inputdispatcher