blob: 64f237268bce324ef904b2ffb61fc4b6b205ae24 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800159
Michael Wrightd02c5b62014-02-10 15:10:22 -0800160public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000161 FakeInputDispatcherPolicy() = default;
162 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800163
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800164 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700165 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700166 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700167 EXPECT_EQ(event.getDisplayId(), args.displayId);
168
169 const auto& keyEvent = static_cast<const KeyEvent&>(event);
170 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
171 EXPECT_EQ(keyEvent.getAction(), args.action);
172 });
Jackal Guof9696682018-10-05 12:23:23 +0800173 }
174
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700175 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
176 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700177 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700178 EXPECT_EQ(event.getDisplayId(), args.displayId);
179
180 const auto& motionEvent = static_cast<const MotionEvent&>(event);
181 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
182 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000183 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
184 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
185 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
186 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700187 });
Jackal Guof9696682018-10-05 12:23:23 +0800188 }
189
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700190 void assertFilterInputEventWasNotCalled() {
191 std::scoped_lock lock(mLock);
192 ASSERT_EQ(nullptr, mFilteredEvent);
193 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800195 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700196 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800197 ASSERT_TRUE(mConfigurationChangedTime)
198 << "Timed out waiting for configuration changed call";
199 ASSERT_EQ(*mConfigurationChangedTime, when);
200 mConfigurationChangedTime = std::nullopt;
201 }
202
203 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800205 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800206 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800207 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
208 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
209 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
210 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
211 mLastNotifySwitch = std::nullopt;
212 }
213
chaviwfd6d3512019-03-25 13:23:49 -0700214 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700215 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800216 ASSERT_EQ(touchedToken, mOnPointerDownToken);
217 mOnPointerDownToken.clear();
218 }
219
220 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700221 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800222 ASSERT_TRUE(mOnPointerDownToken == nullptr)
223 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700224 }
225
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700226 // This function must be called soon after the expected ANR timer starts,
227 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500228 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700229 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500230 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800231 std::unique_lock lock(mLock);
232 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500233 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800234 ASSERT_NO_FATAL_FAILURE(
235 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500236 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700237 }
238
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000239 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800240 const sp<WindowInfoHandle>& window) {
241 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
242 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
243 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 }
245
Prabir Pradhanedd96402022-02-15 01:46:16 -0800246 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
247 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000248 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800249 std::unique_lock lock(mLock);
250 android::base::ScopedLockAssertion assumeLocked(mLock);
251 AnrResult result;
252 ASSERT_NO_FATAL_FAILURE(result =
253 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000254 ASSERT_EQ(expectedToken, result.token);
255 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500256 }
257
Prabir Pradhanedd96402022-02-15 01:46:16 -0800258 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000259 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 std::unique_lock lock(mLock);
261 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
263 const auto& [token, _] = result;
264 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000265 }
266
Prabir Pradhanedd96402022-02-15 01:46:16 -0800267 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800269 std::unique_lock lock(mLock);
270 android::base::ScopedLockAssertion assumeLocked(mLock);
271 AnrResult result;
272 ASSERT_NO_FATAL_FAILURE(
273 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000274 ASSERT_EQ(expectedToken, result.token);
275 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 }
277
278 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 sp<IBinder> getResponsiveWindowToken() {
280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
283 const auto& [token, _] = result;
284 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
287 void assertNotifyAnrWasNotCalled() {
288 std::scoped_lock lock(mLock);
289 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_TRUE(mAnrWindows.empty());
291 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 << "ANR was not called, but please also consume the 'connection is responsive' "
293 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700294 }
295
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000296 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800297 std::unique_lock lock(mLock);
298 base::ScopedLockAssertion assumeLocked(mLock);
299
300 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
301 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000302 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800303 enabled;
304 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000305 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
306 << ") to be called.";
307 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800308 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000309 auto request = *mPointerCaptureRequest;
310 mPointerCaptureRequest.reset();
311 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800312 }
313
314 void assertSetPointerCaptureNotCalled() {
315 std::unique_lock lock(mLock);
316 base::ScopedLockAssertion assumeLocked(mLock);
317
318 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800320 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
325
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700326 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
327 const sp<IBinder>& targetToken) {
328 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800329 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800330 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800331 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800332 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800333 }
334
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800335 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338 std::optional<sp<IBinder>> receivedToken =
339 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
340 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000341 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800342 ASSERT_EQ(token, *receivedToken);
343 }
344
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800345 /**
346 * Set policy timeout. A value of zero means next key will not be intercepted.
347 */
348 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
349 mInterceptKeyTimeout = timeout;
350 }
351
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700352 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
353
Josep del Riob3981622023-04-18 15:49:45 +0000354 void assertUserActivityPoked() {
355 std::scoped_lock lock(mLock);
356 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
357 }
358
359 void assertUserActivityNotPoked() {
360 std::scoped_lock lock(mLock);
361 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
362 }
363
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000364 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000365 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
366 }
367
368 void assertNotifyDeviceInteractionWasNotCalled() {
369 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
370 }
371
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000372 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
373 std::scoped_lock lock(mLock);
374 mUnhandledKeyHandler = handler;
375 }
376
377 void assertUnhandledKeyReported(int32_t keycode) {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380 std::optional<int32_t> unhandledKeycode =
381 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
382 mNotifyUnhandledKey);
383 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
384 ASSERT_EQ(unhandledKeycode, keycode);
385 }
386
387 void assertUnhandledKeyNotReported() {
388 std::unique_lock lock(mLock);
389 base::ScopedLockAssertion assumeLocked(mLock);
390 std::optional<int32_t> unhandledKeycode =
391 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
392 mNotifyUnhandledKey);
393 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
394 }
395
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700397 std::mutex mLock;
398 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
399 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
400 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
401 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800402
Prabir Pradhan99987712020-11-10 18:43:05 -0800403 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000404
405 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800406
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700407 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700408 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800409 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
410 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700411 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800412 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
413 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700414
arthurhungf452d0b2021-01-06 00:19:52 +0800415 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800416 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000417 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800418
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800419 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
420
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700421 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000425 std::condition_variable mNotifyUnhandledKey;
426 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
427 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 return std::nullopt;
472 }
473 T item = storage.front();
474 storage.pop();
475 return std::make_optional(item);
476 }
477
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600478 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700479 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800480 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800481 }
482
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000483 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700485 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 ASSERT_TRUE(pid.has_value());
487 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000492 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 mNotifyAnr.notify_all();
497 }
498
499 void notifyNoFocusedWindowAnr(
500 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
501 std::scoped_lock lock(mLock);
502 mAnrApplications.push(applicationHandle);
503 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800506 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
507 std::scoped_lock lock(mLock);
508 mBrokenInputChannels.push(connectionToken);
509 mNotifyInputChannelBroken.notify_all();
510 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600512 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700513
Chris Yef59a2f42020-10-16 12:55:26 -0700514 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
515 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
516 const std::vector<float>& values) override {}
517
518 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
519 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000520
Chris Yefb552902021-02-03 17:18:37 -0800521 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
522
Prabir Pradhana41d2442023-04-20 21:30:40 +0000523 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700524 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000525 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700526 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000527 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
528 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800529 break;
530 }
531
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700532 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
534 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800535 break;
536 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700537 default: {
538 ADD_FAILURE() << "Should only filter keys or motions";
539 break;
540 }
Jackal Guof9696682018-10-05 12:23:23 +0800541 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800542 return true;
543 }
544
Prabir Pradhana41d2442023-04-20 21:30:40 +0000545 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
546 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800547 // Clear intercept state when we handled the event.
548 mInterceptKeyTimeout = 0ms;
549 }
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800552 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800553
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
556 // Clear intercept state so we could dispatch the event in next wake.
557 mInterceptKeyTimeout = 0ms;
558 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559 }
560
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000561 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000563 std::scoped_lock lock(mLock);
564 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
565 mNotifyUnhandledKey.notify_all();
566 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000575 mLastNotifySwitch =
576 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577 }
578
Josep del Riob3981622023-04-18 15:49:45 +0000579 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
580 std::scoped_lock lock(mLock);
581 mPokedUserActivity = true;
582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700584 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
585 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
586 }
587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700590 mOnPointerDownToken = newToken;
591 }
592
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000593 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800594 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000595 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800596 mPointerCaptureChangedCondition.notify_all();
597 }
598
arthurhungf452d0b2021-01-06 00:19:52 +0800599 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
600 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800601 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800602 mDropTargetWindowToken = token;
603 }
604
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000605 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000606 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000607 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
608 }
609
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700610 void assertFilterInputEventWasCalledInternal(
611 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700612 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800613 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700614 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800615 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800616 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700618} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620// --- InputDispatcherTest ---
621
622class InputDispatcherTest : public testing::Test {
623protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000624 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700625 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000627 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000628 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700629 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
630
Harry Cutts101ee9b2023-07-06 18:04:14 +0000631 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000632 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700633 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634 }
635
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000636 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700637 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700641
642 /**
643 * Used for debugging when writing the test
644 */
645 void dumpDispatcherState() {
646 std::string dump;
647 mDispatcher->dump(dump);
648 std::stringstream ss(dump);
649 std::string to;
650
651 while (std::getline(ss, to, '\n')) {
652 ALOGE("%s", to.c_str());
653 }
654 }
Vishnu Nair958da932020-08-21 17:12:37 -0700655
Chavi Weingarten847e8512023-03-29 00:26:09 +0000656 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700657 FocusRequest request;
658 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000659 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700660 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
661 request.displayId = window->getInfo()->displayId;
662 mDispatcher->setFocusedWindow(request);
663 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664};
665
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
667 KeyEvent event;
668
669 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800670 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
671 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000672 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600673 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800674 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000675 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000676 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677 << "Should reject key events with undefined action.";
678
679 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800680 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
681 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600682 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000684 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000685 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686 << "Should reject key events with ACTION_MULTIPLE.";
687}
688
689TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
690 MotionEvent event;
691 PointerProperties pointerProperties[MAX_POINTERS + 1];
692 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800693 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 pointerProperties[i].clear();
695 pointerProperties[i].id = i;
696 pointerCoords[i].clear();
697 }
698
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800699 // Some constants commonly used below
700 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
701 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
702 constexpr int32_t metaState = AMETA_NONE;
703 constexpr MotionClassification classification = MotionClassification::NONE;
704
chaviw9eaa22c2020-07-01 16:21:27 -0700705 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000708 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000712 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with undefined action.";
717
718 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800719 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800720 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
721 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
723 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000724 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too large.";
729
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 AMOTION_EVENT_ACTION_POINTER_DOWN |
732 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700733 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700735 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000736 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer down index too small.";
741
742 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800744 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
745 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
747 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000748 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too large.";
753
Garfield Tanfbe732e2020-01-24 11:26:14 -0800754 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700755 AMOTION_EVENT_ACTION_POINTER_UP |
756 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700757 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
758 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700759 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000760 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with pointer up index too small.";
765
766 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
768 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700769 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700770 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
771 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000772 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800773 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000774 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000775 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800776 << "Should reject motion events with 0 pointers.";
777
Garfield Tanfbe732e2020-01-24 11:26:14 -0800778 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
779 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700780 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
782 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000783 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800784 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000785 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000786 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800787 << "Should reject motion events with more than MAX_POINTERS pointers.";
788
789 // Rejects motion events with invalid pointer ids.
790 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids less than 0.";
801
802 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000808 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
813
814 // Rejects motion events with duplicate pointer ids.
815 pointerProperties[0].id = 1;
816 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with duplicate pointer ids.";
827}
828
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
830
831TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
832 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000833 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800834 ASSERT_TRUE(mDispatcher->waitForIdle());
835
836 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
837}
838
839TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000840 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
841 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000842 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000843 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800844
845 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
846 args.policyFlags |= POLICY_FLAG_TRUSTED;
847 mFakePolicy->assertNotifySwitchWasCalled(args);
848}
849
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700850namespace {
851
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700852static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700853// Default input dispatching timeout if there is no focused application or paused window
854// from which to determine an appropriate dispatching timeout.
855static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
856 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
857 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800858
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800859class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800860public:
Garfield Tan15601662020-09-22 15:32:38 -0700861 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700862 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800863
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000864 InputEvent* consume(std::chrono::milliseconds timeout, bool handled = false) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700865 InputEvent* event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700866 std::optional<uint32_t> consumeSeq = receiveEvent(timeout, &event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867 if (!consumeSeq) {
868 return nullptr;
869 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000870 finishEvent(*consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 return event;
872 }
873
874 /**
875 * Receive an event without acknowledging it.
876 * Return the sequence number that could later be used to send finished signal.
877 */
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700878 std::optional<uint32_t> receiveEvent(std::chrono::milliseconds timeout,
879 InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 uint32_t consumeSeq;
881 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800882
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 std::chrono::time_point start = std::chrono::steady_clock::now();
884 status_t status = WOULD_BLOCK;
885 while (status == WOULD_BLOCK) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700886 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
887 &event);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700889 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 break;
891 }
892 }
893
894 if (status == WOULD_BLOCK) {
895 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700896 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800897 }
898
899 if (status != OK) {
900 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700901 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 }
903 if (event == nullptr) {
904 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800906 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700907 if (outEvent != nullptr) {
908 *outEvent = event;
909 }
910 return consumeSeq;
911 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800912
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700913 /**
914 * To be used together with "receiveEvent" to complete the consumption of an event.
915 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000916 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700917 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700918 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800919 }
920
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000921 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700922 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000923 ASSERT_EQ(OK, status);
924 }
925
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700926 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000927 std::optional<int32_t> expectedDisplayId,
928 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700929 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
931 ASSERT_NE(nullptr, event) << mName.c_str()
932 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800933 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700934 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
935 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800936
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000937 if (expectedDisplayId.has_value()) {
938 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
939 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800940
Tiger Huang8664f8c2018-10-11 19:14:35 +0800941 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700942 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800943 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700944 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 if (expectedFlags.has_value()) {
946 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
947 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800948 break;
949 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700950 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800951 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700952 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000953 if (expectedFlags.has_value()) {
954 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
955 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800956 break;
957 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100959 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
960 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700961 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800962 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000965 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
966 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700967 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800968 FAIL() << "Use 'consumeDragEvent' for DRAG events";
969 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800970 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800971 }
972
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800973 MotionEvent* consumeMotion() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700974 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800975
976 if (event == nullptr) {
977 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
978 return nullptr;
979 }
980
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 if (event->getType() != InputEventType::MOTION) {
982 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800983 return nullptr;
984 }
985 return static_cast<MotionEvent*>(event);
986 }
987
988 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
989 MotionEvent* motionEvent = consumeMotion();
990 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
991 ASSERT_THAT(*motionEvent, matcher);
992 }
993
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100994 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700995 InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100996 ASSERT_NE(nullptr, event) << mName.c_str()
997 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700998 ASSERT_EQ(InputEventType::FOCUS, event->getType())
999 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001000
1001 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1002 << mName.c_str() << ": event displayId should always be NONE.";
1003
1004 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1005 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001006 }
1007
Prabir Pradhan99987712020-11-10 18:43:05 -08001008 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001009 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001010 ASSERT_NE(nullptr, event) << mName.c_str()
1011 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1013 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001014
1015 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1016 << mName.c_str() << ": event displayId should always be NONE.";
1017
1018 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1019 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1020 }
1021
arthurhungb89ccb02020-12-30 16:19:01 +08001022 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001023 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001024 ASSERT_NE(nullptr, event) << mName.c_str()
1025 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001026 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001027
1028 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1029 << mName.c_str() << ": event displayId should always be NONE.";
1030
1031 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1032 EXPECT_EQ(isExiting, dragEvent.isExiting());
1033 EXPECT_EQ(x, dragEvent.getX());
1034 EXPECT_EQ(y, dragEvent.getY());
1035 }
1036
Antonio Kantekf16f2832021-09-28 04:39:20 +00001037 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001038 const InputEvent* event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001039 ASSERT_NE(nullptr, event) << mName.c_str()
1040 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001041 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1042 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001043
1044 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1047 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1048 }
1049
chaviwd1c23182019-12-20 18:44:56 -08001050 void assertNoEvents() {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001051 InputEvent* event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001052 if (event == nullptr) {
1053 return;
1054 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001056 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001057 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001060 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1063 ADD_FAILURE() << "Received focus event, hasFocus = "
1064 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001066 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1067 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1068 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001070 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1071 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1072 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001073 }
1074 FAIL() << mName.c_str()
1075 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001076 }
1077
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001078 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001079
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001080 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001081
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001082private:
1083 InputConsumer mConsumer;
chaviwd1c23182019-12-20 18:44:56 -08001084 PreallocatedInputEventFactory mEventFactory;
1085
1086 std::string mName;
1087};
1088
chaviw3277faf2021-05-19 16:45:23 -05001089class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001090public:
1091 static const int32_t WIDTH = 600;
1092 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001093
Chris Yea209fde2020-07-22 13:54:51 -07001094 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001095 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001096 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001097 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001098 sp<IBinder> token;
1099 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001100 base::Result<std::unique_ptr<InputChannel>> channel =
1101 dispatcher->createInputChannel(name);
1102 token = (*channel)->getConnectionToken();
1103 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001104 }
1105
1106 inputApplicationHandle->updateInfo();
1107 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1108
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001109 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001110 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001111 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001112 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001113 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001114 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001115 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001116 mInfo.globalScaleFactor = 1.0;
1117 mInfo.touchableRegion.clear();
1118 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001119 mInfo.ownerPid = WINDOW_PID;
1120 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001121 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001122 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001123 }
1124
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001125 sp<FakeWindowHandle> clone(int32_t displayId) {
1126 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1127 handle->mInfo = mInfo;
1128 handle->mInfo.displayId = displayId;
1129 handle->mInfo.id = sId++;
1130 handle->mInputReceiver = mInputReceiver;
1131 return handle;
1132 }
1133
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001134 void setTouchable(bool touchable) {
1135 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1136 }
chaviwd1c23182019-12-20 18:44:56 -08001137
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001138 void setFocusable(bool focusable) {
1139 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1140 }
1141
1142 void setVisible(bool visible) {
1143 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1144 }
Vishnu Nair958da932020-08-21 17:12:37 -07001145
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001146 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001147 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001148 }
1149
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001150 void setPaused(bool paused) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1152 }
1153
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001154 void setPreventSplitting(bool preventSplitting) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001156 }
1157
1158 void setSlippery(bool slippery) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1160 }
1161
1162 void setWatchOutsideTouch(bool watchOutside) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1164 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001165
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001166 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1167
1168 void setInterceptsStylus(bool interceptsStylus) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1170 }
1171
1172 void setDropInput(bool dropInput) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1174 }
1175
1176 void setDropInputIfObscured(bool dropInputIfObscured) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1178 }
1179
1180 void setNoInputChannel(bool noInputChannel) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1182 }
1183
Josep del Riob3981622023-04-18 15:49:45 +00001184 void setDisableUserActivity(bool disableUserActivity) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1186 }
1187
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001188 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1190 shouldGlobalStylusBlockTouch);
1191 }
1192
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001193 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1194
chaviw3277faf2021-05-19 16:45:23 -05001195 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001196
Bernardo Rufino7393d172021-02-26 13:56:11 +00001197 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1198
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001199 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001200 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001201 mInfo.touchableRegion.clear();
1202 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001203
1204 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1205 ui::Transform translate;
1206 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1207 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001208 }
1209
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001210 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setIsWallpaper(bool isWallpaper) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1214 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001215
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 void setDupTouchToWallpaper(bool hasWallpaper) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1218 }
chaviwd1c23182019-12-20 18:44:56 -08001219
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001220 void setTrustedOverlay(bool trustedOverlay) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1222 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001223
chaviw9eaa22c2020-07-01 16:21:27 -07001224 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1225 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1226 }
1227
1228 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001229
yunho.shinf4a80b82020-11-16 21:13:57 +09001230 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1231
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001232 const KeyEvent& consumeKey(bool handled = true) {
1233 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1234 if (event.getType() != InputEventType::KEY) {
1235 LOG(FATAL) << "Instead of key event, got " << event;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001236 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001237 return static_cast<const KeyEvent&>(event);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001238 }
1239
1240 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001241 const KeyEvent& keyEvent = consumeKey();
1242 ASSERT_THAT(keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001243 }
1244
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001245 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001246 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1247 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001248 }
1249
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001250 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001251 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1252 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001253 }
1254
Svet Ganov5d3bc372020-01-26 23:11:07 -08001255 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001256 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001257 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1258 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001259 }
1260
1261 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001262 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001263 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1264 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001265 }
1266
1267 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001268 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001269 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1270 }
1271
1272 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1273 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001274 consumeMotionEvent(
1275 AllOf(WithMotionAction(ACTION_DOWN),
1276 testing::Conditional(expectedDisplayId.has_value(),
1277 WithDisplayId(*expectedDisplayId), testing::_),
1278 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1279 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001280 }
1281
Svet Ganov5d3bc372020-01-26 23:11:07 -08001282 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1284 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001285 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001287 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1288 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001289 }
1290
1291 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001293 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001294 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001295 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1296 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 }
1298
1299 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001300 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001301 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1302 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001303 }
1304
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001305 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1306 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001307 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1308 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001309 }
1310
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001311 void consumeMotionOutsideWithZeroedCoords() {
1312 consumeMotionEvent(
1313 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001314 }
1315
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001316 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1317 ASSERT_NE(mInputReceiver, nullptr)
1318 << "Cannot consume events from a window with no receiver";
1319 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1320 }
1321
Prabir Pradhan99987712020-11-10 18:43:05 -08001322 void consumeCaptureEvent(bool hasCapture) {
1323 ASSERT_NE(mInputReceiver, nullptr)
1324 << "Cannot consume events from a window with no receiver";
1325 mInputReceiver->consumeCaptureEvent(hasCapture);
1326 }
1327
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001328 const MotionEvent& consumeMotionEvent(
1329 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
1330 const InputEvent& event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1331 if (event.getType() != InputEventType::MOTION) {
1332 LOG(FATAL) << "Instead of motion event, got " << event;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001333 }
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001334 const auto& motionEvent = static_cast<const MotionEvent&>(event);
1335 EXPECT_THAT(motionEvent, matcher);
1336 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001354 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED, outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
Arthur Hungb92218b2018-08-14 12:00:21 +08001367 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001368 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001369 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001370 return; // Can't receive events if the window does not have input channel
1371 }
1372 ASSERT_NE(nullptr, mInputReceiver)
1373 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001374 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001375 }
1376
chaviwaf87b3e2019-10-01 16:59:28 -07001377 sp<IBinder> getToken() { return mInfo.token; }
1378
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001379 const std::string& getName() { return mName; }
1380
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001381 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001382 mInfo.ownerPid = ownerPid;
1383 mInfo.ownerUid = ownerUid;
1384 }
1385
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001386 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001388 void destroyReceiver() { mInputReceiver = nullptr; }
1389
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001390 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1391
chaviwd1c23182019-12-20 18:44:56 -08001392private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001393 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001394 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001395 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001396 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001397 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001398
1399 const InputEvent& consume(std::chrono::milliseconds timeout, bool handled = true) {
1400 if (mInputReceiver == nullptr) {
1401 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1402 }
1403 InputEvent* event = mInputReceiver->consume(timeout, handled);
1404 if (event == nullptr) {
1405 LOG(FATAL) << "Consume failed: no event";
1406 }
1407 return *event;
1408 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001409};
1410
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001411std::atomic<int32_t> FakeWindowHandle::sId{1};
1412
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001413class FakeMonitorReceiver {
1414public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001415 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1416 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001417
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001418 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001419
1420 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001421 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1422 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001423 }
1424
1425 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 return mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001427 }
1428
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001429 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001430
1431 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001432 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1433 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001434 }
1435
1436 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001437 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1438 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001439 }
1440
1441 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001442 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1443 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001444 }
1445
1446 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001447 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001448 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1449 WithDisplayId(expectedDisplayId),
1450 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1451 }
1452
1453 void consumeMotionPointerDown(int32_t pointerIdx) {
1454 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1455 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001456 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1457 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001458 }
1459
1460 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001461 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001462 }
1463
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001464 MotionEvent* consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001465
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001466 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467
1468private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001469 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001470};
1471
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001472static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001473 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001474 int32_t displayId = ADISPLAY_ID_NONE,
1475 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001476 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001477 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001478 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001479 KeyEvent event;
1480 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1481
1482 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001483 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001484 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1485 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001486
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001487 if (!allowKeyRepeat) {
1488 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1489 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001490 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001491 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001492}
1493
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001494static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1495 InputEventInjectionResult result =
1496 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1497 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1498 if (result != InputEventInjectionResult::TIMED_OUT) {
1499 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1500 }
1501}
1502
1503static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001504 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001505 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001506}
1507
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001508// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1509// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1510// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001511static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1512 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001513 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001514 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001515 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001516}
1517
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001518static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001520 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001521}
1522
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001523static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001524 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001525 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001526 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001527 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001528 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1529 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001530}
1531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001533 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1534 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001535 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001536 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1537 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001538 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001539 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001540 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001541 MotionEventBuilder motionBuilder =
1542 MotionEventBuilder(action, source)
1543 .displayId(displayId)
1544 .eventTime(eventTime)
1545 .rawXCursorPosition(cursorPosition.x)
1546 .rawYCursorPosition(cursorPosition.y)
1547 .pointer(
1548 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1549 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1550 motionBuilder.downTime(eventTime);
1551 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001552
1553 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001554 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1555 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001556}
1557
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001558static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1559 int32_t displayId,
1560 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001561 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001562}
1563
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001564static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1565 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001566 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001567 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001568}
1569
Jackal Guof9696682018-10-05 12:23:23 +08001570static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1571 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1572 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001573 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1574 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1575 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001576
1577 return args;
1578}
1579
Josep del Riob3981622023-04-18 15:49:45 +00001580static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1581 int32_t displayId = ADISPLAY_ID_NONE) {
1582 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1583 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001584 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1585 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1586 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001587
1588 return args;
1589}
1590
1591static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1592 int32_t displayId = ADISPLAY_ID_NONE) {
1593 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1594 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001595 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1596 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1597 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001598
1599 return args;
1600}
1601
Prabir Pradhan678438e2023-04-13 19:32:51 +00001602[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1603 int32_t displayId,
1604 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001605 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001606 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1607 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1608 }
1609
chaviwd1c23182019-12-20 18:44:56 -08001610 PointerProperties pointerProperties[pointerCount];
1611 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001612
chaviwd1c23182019-12-20 18:44:56 -08001613 for (size_t i = 0; i < pointerCount; i++) {
1614 pointerProperties[i].clear();
1615 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001616 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001617
chaviwd1c23182019-12-20 18:44:56 -08001618 pointerCoords[i].clear();
1619 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1620 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1621 }
Jackal Guof9696682018-10-05 12:23:23 +08001622
1623 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1624 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001625 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1626 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1627 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001628 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001629 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001630 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001631 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001632
1633 return args;
1634}
1635
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001636static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1637 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1638}
1639
chaviwd1c23182019-12-20 18:44:56 -08001640static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1641 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1642}
1643
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001644static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1645 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001646 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1647 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001648}
1649
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001650} // namespace
1651
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001652/**
1653 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1654 * broken channel.
1655 */
1656TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1658 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001659 sp<FakeWindowHandle>::make(application, mDispatcher,
1660 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001661
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001662 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001663
1664 // Window closes its channel, but the window remains.
1665 window->destroyReceiver();
1666 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1667}
1668
Arthur Hungb92218b2018-08-14 12:00:21 +08001669TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001671 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1672 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001674 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001676 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001678
1679 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001680 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001681}
1682
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001683TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001685 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1686 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001687
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001688 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001689 // Inject a MotionEvent to an unknown display.
1690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001691 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1693
1694 // Window should receive motion event.
1695 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1696}
1697
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001698/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001699 * Calling onWindowInfosChanged once should not cause any issues.
1700 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001701 * called twice.
1702 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001703TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1706 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714
1715 // Window should receive motion event.
1716 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1717}
1718
1719/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001720 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721 */
1722TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001724 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1725 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001727
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001731 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001732 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001734
1735 // Window should receive motion event.
1736 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1737}
1738
Arthur Hungb92218b2018-08-14 12:00:21 +08001739// The foreground window should receive the first touch down event.
1740TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001742 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001743 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001744 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001745 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001746
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001747 mDispatcher->onWindowInfosChanged(
1748 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001750 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001751 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001752
1753 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001754 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001755 windowSecond->assertNoEvents();
1756}
1757
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001758/**
1759 * Two windows: A top window, and a wallpaper behind the window.
1760 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1761 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001762 * 1. foregroundWindow <-- dup touch to wallpaper
1763 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001764 */
1765TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1767 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001768 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001769 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001770 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001771 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001772 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001773
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001774 mDispatcher->onWindowInfosChanged(
1775 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001777 injectMotionEvent(*mDispatcher,
1778 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1779 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1780 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1782
1783 // Both foreground window and its wallpaper should receive the touch down
1784 foregroundWindow->consumeMotionDown();
1785 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1786
1787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001788 injectMotionEvent(*mDispatcher,
1789 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1790 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1791 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1793
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001794 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001795 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1796
1797 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001798 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001799 foregroundWindow->consumeMotionCancel();
1800 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1801 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1802}
1803
1804/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001805 * Two fingers down on the window, and lift off the first finger.
1806 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1807 * contains a single pointer.
1808 */
1809TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1811 sp<FakeWindowHandle> window =
1812 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001814 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001815 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1817 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1818 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001819 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001820 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1821 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1822 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1823 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001824 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001825 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1826 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1827 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1828 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001829 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1830 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1831 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1832
1833 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001834 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001835 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1836 window->consumeMotionEvent(
1837 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1838}
1839
1840/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001841 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1842 * with the following differences:
1843 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1844 * clean up the connection.
1845 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1846 * Ensure that there's no crash in the dispatcher.
1847 */
1848TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1850 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001852 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001853 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001854 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001855 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001857 mDispatcher->onWindowInfosChanged(
1858 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001860 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001861 {100, 200}))
1862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1863
1864 // Both foreground window and its wallpaper should receive the touch down
1865 foregroundWindow->consumeMotionDown();
1866 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1867
1868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001869 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001870 ADISPLAY_ID_DEFAULT, {110, 200}))
1871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1872
1873 foregroundWindow->consumeMotionMove();
1874 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1875
1876 // Wallpaper closes its channel, but the window remains.
1877 wallpaperWindow->destroyReceiver();
1878 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1879
1880 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1881 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001882 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001883 foregroundWindow->consumeMotionCancel();
1884}
1885
Arthur Hungc539dbb2022-12-08 07:45:36 +00001886class ShouldSplitTouchFixture : public InputDispatcherTest,
1887 public ::testing::WithParamInterface<bool> {};
1888INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1889 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001890/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 * A single window that receives touch (on top), and a wallpaper window underneath it.
1892 * The top window gets a multitouch gesture.
1893 * Ensure that wallpaper gets the same gesture.
1894 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001897 sp<FakeWindowHandle> foregroundWindow =
1898 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1899 foregroundWindow->setDupTouchToWallpaper(true);
1900 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001901
1902 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001903 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001904 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001906 mDispatcher->onWindowInfosChanged(
1907 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001908
1909 // Touch down on top window
1910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001911 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 {100, 100}))
1913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1914
1915 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001916 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1918
1919 // Second finger down on the top window
1920 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001921 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001922 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001923 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1924 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001925 .build();
1926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001927 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001928 InputEventInjectionSync::WAIT_FOR_RESULT))
1929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1930
Harry Cutts33476232023-01-30 19:57:29 +00001931 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1932 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001934
1935 const MotionEvent secondFingerUpEvent =
1936 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1937 .displayId(ADISPLAY_ID_DEFAULT)
1938 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001939 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1940 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001941 .build();
1942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001943 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001944 InputEventInjectionSync::WAIT_FOR_RESULT))
1945 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1946 foregroundWindow->consumeMotionPointerUp(0);
1947 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1948
1949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001950 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001951 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1952 AINPUT_SOURCE_TOUCHSCREEN)
1953 .displayId(ADISPLAY_ID_DEFAULT)
1954 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001955 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001956 .x(100)
1957 .y(100))
1958 .build(),
1959 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1961 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1962 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963}
1964
1965/**
1966 * Two windows: a window on the left and window on the right.
1967 * A third window, wallpaper, is behind both windows, and spans both top windows.
1968 * The first touch down goes to the left window. A second pointer touches down on the right window.
1969 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1970 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1971 * ACTION_POINTER_DOWN(1).
1972 */
1973TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1975 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001978 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001979
1980 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001981 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001982 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001983 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001984
1985 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001986 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001988 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001990 mDispatcher->onWindowInfosChanged(
1991 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1992 {},
1993 0,
1994 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001995
1996 // Touch down on left window
1997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001998 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 {100, 100}))
2000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2001
2002 // Both foreground window and its wallpaper should receive the touch down
2003 leftWindow->consumeMotionDown();
2004 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2005
2006 // Second finger down on the right window
2007 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002008 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002010 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2011 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012 .build();
2013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002014 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 InputEventInjectionSync::WAIT_FOR_RESULT))
2016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2017
2018 leftWindow->consumeMotionMove();
2019 // Since the touch is split, right window gets ACTION_DOWN
2020 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002021 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002022 expectedWallpaperFlags);
2023
2024 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002025 mDispatcher->onWindowInfosChanged(
2026 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 leftWindow->consumeMotionCancel();
2028 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2029 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2030
2031 // The pointer that's still down on the right window moves, and goes to the right window only.
2032 // As far as the dispatcher's concerned though, both pointers are still present.
2033 const MotionEvent secondFingerMoveEvent =
2034 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2035 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002036 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2037 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002038 .build();
2039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002040 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002041 InputEventInjectionSync::WAIT_FOR_RESULT));
2042 rightWindow->consumeMotionMove();
2043
2044 leftWindow->assertNoEvents();
2045 rightWindow->assertNoEvents();
2046 wallpaperWindow->assertNoEvents();
2047}
2048
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049/**
2050 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2051 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2052 * The right window should receive ACTION_DOWN.
2053 */
2054TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002055 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 sp<FakeWindowHandle> leftWindow =
2057 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2058 leftWindow->setFrame(Rect(0, 0, 200, 200));
2059 leftWindow->setDupTouchToWallpaper(true);
2060 leftWindow->setSlippery(true);
2061
2062 sp<FakeWindowHandle> rightWindow =
2063 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2064 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002065
2066 sp<FakeWindowHandle> wallpaperWindow =
2067 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2068 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002069
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002070 mDispatcher->onWindowInfosChanged(
2071 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2072 {},
2073 0,
2074 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002075
Arthur Hungc539dbb2022-12-08 07:45:36 +00002076 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002078 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002079 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081
2082 // Both foreground window and its wallpaper should receive the touch down
2083 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002084 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2085
Arthur Hungc539dbb2022-12-08 07:45:36 +00002086 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002088 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002089 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2091
Arthur Hungc539dbb2022-12-08 07:45:36 +00002092 leftWindow->consumeMotionCancel();
2093 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2094 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002095}
2096
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002097/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002098 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2099 * interactive, it might stop sending this flag.
2100 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2101 * to have a consistent input stream.
2102 *
2103 * Test procedure:
2104 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2105 * DOWN (new gesture).
2106 *
2107 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2108 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2109 *
2110 * We technically just need a single window here, but we are using two windows (spy on top and a
2111 * regular window below) to emulate the actual situation where it happens on the device.
2112 */
2113TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2114 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2115 sp<FakeWindowHandle> spyWindow =
2116 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2117 spyWindow->setFrame(Rect(0, 0, 200, 200));
2118 spyWindow->setTrustedOverlay(true);
2119 spyWindow->setSpy(true);
2120
2121 sp<FakeWindowHandle> window =
2122 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2123 window->setFrame(Rect(0, 0, 200, 200));
2124
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002125 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127
2128 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002129 mDispatcher->notifyMotion(
2130 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2131 .deviceId(touchDeviceId)
2132 .policyFlags(DEFAULT_POLICY_FLAGS)
2133 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2134 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135
Prabir Pradhan678438e2023-04-13 19:32:51 +00002136 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2137 .deviceId(touchDeviceId)
2138 .policyFlags(DEFAULT_POLICY_FLAGS)
2139 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2140 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2141 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002142 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2143 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2144 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2145 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2146
2147 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002148 mDispatcher->notifyMotion(
2149 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2150 .deviceId(touchDeviceId)
2151 .policyFlags(0)
2152 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2153 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2154 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002155 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2156 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2157
2158 // We don't need to reset the device to reproduce the issue, but the reset event typically
2159 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002160 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002161
2162 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002163 mDispatcher->notifyMotion(
2164 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2165 .deviceId(touchDeviceId)
2166 .policyFlags(DEFAULT_POLICY_FLAGS)
2167 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2168 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002169 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2170 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2171
2172 // No more events
2173 spyWindow->assertNoEvents();
2174 window->assertNoEvents();
2175}
2176
2177/**
Linnan Li907ae732023-09-05 17:14:21 +08002178 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2179 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2180 * interactive, it might stop sending this flag.
2181 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2182 * the consistency of the hover event in this case.
2183 *
2184 * Test procedure:
2185 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2186 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2187 *
2188 * We expect to receive two full streams of hover events.
2189 */
2190TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2192
2193 sp<FakeWindowHandle> window =
2194 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2195 window->setFrame(Rect(0, 0, 300, 300));
2196
2197 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2198
2199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2200 .policyFlags(DEFAULT_POLICY_FLAGS)
2201 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2202 .build());
2203 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2204
2205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2206 .policyFlags(DEFAULT_POLICY_FLAGS)
2207 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2208 .build());
2209 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2210
2211 // Send hover exit without the default policy flags.
2212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2213 .policyFlags(0)
2214 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2215 .build());
2216
2217 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2218
2219 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2220 // right event.
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2222 .policyFlags(DEFAULT_POLICY_FLAGS)
2223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2224 .build());
2225 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2226
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2228 .policyFlags(DEFAULT_POLICY_FLAGS)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2230 .build());
2231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2232
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2234 .policyFlags(DEFAULT_POLICY_FLAGS)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2236 .build());
2237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2238}
2239
2240/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002241 * Two windows: a window on the left and a window on the right.
2242 * Mouse is hovered from the right window into the left window.
2243 * Next, we tap on the left window, where the cursor was last seen.
2244 * The second tap is done onto the right window.
2245 * The mouse and tap are from two different devices.
2246 * We technically don't need to set the downtime / eventtime for these events, but setting these
2247 * explicitly helps during debugging.
2248 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2249 * In the buggy implementation, a tap on the right window would cause a crash.
2250 */
2251TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2253 sp<FakeWindowHandle> leftWindow =
2254 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2255 leftWindow->setFrame(Rect(0, 0, 200, 200));
2256
2257 sp<FakeWindowHandle> rightWindow =
2258 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2259 rightWindow->setFrame(Rect(200, 0, 400, 200));
2260
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002261 mDispatcher->onWindowInfosChanged(
2262 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002263 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2264 // stale.
2265 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2266 const int32_t mouseDeviceId = 6;
2267 const int32_t touchDeviceId = 4;
2268 // Move the cursor from right
2269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002270 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002271 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2272 AINPUT_SOURCE_MOUSE)
2273 .deviceId(mouseDeviceId)
2274 .downTime(baseTime + 10)
2275 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002276 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002277 .build()));
2278 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2279
2280 // .. to the left window
2281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002283 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2284 AINPUT_SOURCE_MOUSE)
2285 .deviceId(mouseDeviceId)
2286 .downTime(baseTime + 10)
2287 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002288 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002289 .build()));
2290 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2291 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2292 // Now tap the left window
2293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002294 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002295 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2296 AINPUT_SOURCE_TOUCHSCREEN)
2297 .deviceId(touchDeviceId)
2298 .downTime(baseTime + 40)
2299 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002300 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002301 .build()));
2302 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2303 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2304
2305 // release tap
2306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002307 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002308 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2309 AINPUT_SOURCE_TOUCHSCREEN)
2310 .deviceId(touchDeviceId)
2311 .downTime(baseTime + 40)
2312 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002313 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002314 .build()));
2315 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2316
2317 // Tap the window on the right
2318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002319 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2321 AINPUT_SOURCE_TOUCHSCREEN)
2322 .deviceId(touchDeviceId)
2323 .downTime(baseTime + 60)
2324 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002325 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002326 .build()));
2327 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2328
2329 // release tap
2330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002331 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2333 AINPUT_SOURCE_TOUCHSCREEN)
2334 .deviceId(touchDeviceId)
2335 .downTime(baseTime + 60)
2336 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002337 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002338 .build()));
2339 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2340
2341 // No more events
2342 leftWindow->assertNoEvents();
2343 rightWindow->assertNoEvents();
2344}
2345
2346/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002347 * Start hovering in a window. While this hover is still active, make another window appear on top.
2348 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2349 * While the top window is present, the hovering is stopped.
2350 * Later, hovering gets resumed again.
2351 * Ensure that new hover gesture is handled correctly.
2352 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2353 * to the window that's currently being hovered over.
2354 */
2355TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2357 sp<FakeWindowHandle> window =
2358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2359 window->setFrame(Rect(0, 0, 200, 200));
2360
2361 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002362 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002363
2364 // Start hovering in the window
2365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2366 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2367 .build());
2368 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2369
2370 // Now, an obscuring window appears!
2371 sp<FakeWindowHandle> obscuringWindow =
2372 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2373 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002374 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002375 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2376 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2377 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2378 obscuringWindow->setNoInputChannel(true);
2379 obscuringWindow->setFocusable(false);
2380 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002381 mDispatcher->onWindowInfosChanged(
2382 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002383
2384 // While this new obscuring window is present, the hovering is stopped
2385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2386 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2387 .build());
2388 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2389
2390 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002392
2393 // And a new hover gesture starts.
2394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2396 .build());
2397 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2398}
2399
2400/**
2401 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2402 * the obscuring window.
2403 */
2404TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2406 sp<FakeWindowHandle> window =
2407 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2408 window->setFrame(Rect(0, 0, 200, 200));
2409
2410 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002411 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002412
2413 // Start hovering in the window
2414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2415 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2416 .build());
2417 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2418
2419 // Now, an obscuring window appears!
2420 sp<FakeWindowHandle> obscuringWindow =
2421 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2422 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002423 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002424 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2425 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2426 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2427 obscuringWindow->setNoInputChannel(true);
2428 obscuringWindow->setFocusable(false);
2429 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002430 mDispatcher->onWindowInfosChanged(
2431 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002432
2433 // While this new obscuring window is present, the hovering continues. The event can't go to the
2434 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2435 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2436 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2437 .build());
2438 obscuringWindow->assertNoEvents();
2439 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2440
2441 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002442 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002443
2444 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2445 // so it should generate a HOVER_ENTER
2446 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2447 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2448 .build());
2449 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2450
2451 // Now the MOVE should be getting dispatched normally
2452 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2453 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2454 .build());
2455 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2456}
2457
2458/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002459 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2460 * events are delivered to the window.
2461 */
2462TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2464 sp<FakeWindowHandle> window =
2465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2466 window->setFrame(Rect(0, 0, 200, 200));
2467 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2468
2469 // Start hovering in the window
2470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2472 .build());
2473 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2474
2475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2476 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2477 .build());
2478 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2479
2480 // Scroll with the mouse
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2482 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2483 .build());
2484 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2485}
2486
2487using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2488
2489/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002490 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2491 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002492 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002493TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2495 sp<FakeWindowHandle> window =
2496 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2497 window->setFrame(Rect(0, 0, 200, 200));
2498
2499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2500
2501 constexpr int32_t touchDeviceId = 4;
2502 constexpr int32_t stylusDeviceId = 2;
2503
2504 // Stylus down
2505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2506 .deviceId(stylusDeviceId)
2507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2508 .build());
2509 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2510
2511 // Touch down
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2513 .deviceId(touchDeviceId)
2514 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2515 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002516
2517 // Touch move
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2521 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002522 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002523
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002524 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2526 .deviceId(stylusDeviceId)
2527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2528 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002529 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2530 WithCoords(101, 111)));
2531
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002532 window->assertNoEvents();
2533}
2534
2535/**
2536 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002537 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002538 * Similar test as above, but with added SPY window.
2539 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002540TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2542 sp<FakeWindowHandle> window =
2543 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2544 sp<FakeWindowHandle> spyWindow =
2545 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2546 spyWindow->setFrame(Rect(0, 0, 200, 200));
2547 spyWindow->setTrustedOverlay(true);
2548 spyWindow->setSpy(true);
2549 window->setFrame(Rect(0, 0, 200, 200));
2550
2551 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2552
2553 constexpr int32_t touchDeviceId = 4;
2554 constexpr int32_t stylusDeviceId = 2;
2555
2556 // Stylus down
2557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2558 .deviceId(stylusDeviceId)
2559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2560 .build());
2561 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2562 spyWindow->consumeMotionEvent(
2563 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2564
2565 // Touch down
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2567 .deviceId(touchDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2569 .build());
2570
2571 // Touch move
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2573 .deviceId(touchDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2575 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002576
2577 // Touch is ignored because stylus is already down
2578
2579 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2581 .deviceId(stylusDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2583 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2585 WithCoords(101, 111)));
2586 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2587 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002588
2589 window->assertNoEvents();
2590 spyWindow->assertNoEvents();
2591}
2592
2593/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002594 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002595 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002596 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002597TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2599 sp<FakeWindowHandle> window =
2600 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2601 window->setFrame(Rect(0, 0, 200, 200));
2602
2603 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2604
2605 constexpr int32_t touchDeviceId = 4;
2606 constexpr int32_t stylusDeviceId = 2;
2607
2608 // Stylus down on the window
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2610 .deviceId(stylusDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2612 .build());
2613 window->consumeMotionEvent(
2614 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2615
2616 // Touch down on window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2618 .deviceId(touchDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2620 .build());
2621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2622 .deviceId(touchDeviceId)
2623 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2624 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002625
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002626 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002627
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002628 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2630 .deviceId(stylusDeviceId)
2631 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2632 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002633 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2634 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002635
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002636 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2638 .deviceId(touchDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2640 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002641 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002642}
2643
2644/**
2645 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002646 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002647 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002648TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2650 sp<FakeWindowHandle> window =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2652 window->setFrame(Rect(0, 0, 200, 200));
2653
2654 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2655
2656 constexpr int32_t touchDeviceId = 4;
2657 constexpr int32_t stylusDeviceId = 2;
2658
2659 // Touch down on window
2660 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2661 .deviceId(touchDeviceId)
2662 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2663 .build());
2664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2665 .deviceId(touchDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2667 .build());
2668 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2669 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2670
2671 // Stylus hover on the window
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2673 .deviceId(stylusDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2675 .build());
2676 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2677 .deviceId(stylusDeviceId)
2678 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2679 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002680 // Stylus hover movement causes touch to be canceled
2681 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2682 WithCoords(141, 146)));
2683 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2684 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2685 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2686 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002687
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002688 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002689 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2690 .deviceId(touchDeviceId)
2691 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2692 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002693
2694 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002695}
2696
2697/**
2698 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2699 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2700 * become active.
2701 */
2702TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2704 sp<FakeWindowHandle> window =
2705 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2706 window->setFrame(Rect(0, 0, 200, 200));
2707
2708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2709
2710 constexpr int32_t stylusDeviceId1 = 3;
2711 constexpr int32_t stylusDeviceId2 = 5;
2712
2713 // Touch down on window
2714 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2715 .deviceId(stylusDeviceId1)
2716 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2717 .build());
2718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2719 .deviceId(stylusDeviceId1)
2720 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2721 .build());
2722 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2723 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2724
2725 // Second stylus down
2726 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2727 .deviceId(stylusDeviceId2)
2728 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2729 .build());
2730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2731 .deviceId(stylusDeviceId2)
2732 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2733 .build());
2734
2735 // First stylus is canceled, second one takes over.
2736 window->consumeMotionEvent(
2737 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2738 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2739 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2740
2741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2742 .deviceId(stylusDeviceId1)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2744 .build());
2745 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002746 window->assertNoEvents();
2747}
2748
2749/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002750 * One window. Touch down on the window. Then, stylus down on the window from another device.
2751 * Ensure that is canceled, because stylus down should be preferred over touch.
2752 */
2753TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2754 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2755 sp<FakeWindowHandle> window =
2756 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2757 window->setFrame(Rect(0, 0, 200, 200));
2758
2759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2760
2761 constexpr int32_t touchDeviceId = 4;
2762 constexpr int32_t stylusDeviceId = 2;
2763
2764 // Touch down on window
2765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2766 .deviceId(touchDeviceId)
2767 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2768 .build());
2769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2770 .deviceId(touchDeviceId)
2771 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2772 .build());
2773 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2775
2776 // Stylus down on the window
2777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2778 .deviceId(stylusDeviceId)
2779 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2780 .build());
2781 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2783
2784 // Subsequent stylus movements are delivered correctly
2785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2786 .deviceId(stylusDeviceId)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2788 .build());
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2790 WithCoords(101, 111)));
2791}
2792
2793/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002794 * Two windows: a window on the left and a window on the right.
2795 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2796 * down. Then, on the left window, also place second touch pointer down.
2797 * This test tries to reproduce a crash.
2798 * In the buggy implementation, second pointer down on the left window would cause a crash.
2799 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002800TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2802 sp<FakeWindowHandle> leftWindow =
2803 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2804 leftWindow->setFrame(Rect(0, 0, 200, 200));
2805
2806 sp<FakeWindowHandle> rightWindow =
2807 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2808 rightWindow->setFrame(Rect(200, 0, 400, 200));
2809
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002810 mDispatcher->onWindowInfosChanged(
2811 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812
2813 const int32_t touchDeviceId = 4;
2814 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002815
2816 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2818 .deviceId(mouseDeviceId)
2819 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2820 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821 leftWindow->consumeMotionEvent(
2822 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2823
2824 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2826 .deviceId(mouseDeviceId)
2827 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2829 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002830
2831 leftWindow->consumeMotionEvent(
2832 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2833 leftWindow->consumeMotionEvent(
2834 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2835
Prabir Pradhan678438e2023-04-13 19:32:51 +00002836 mDispatcher->notifyMotion(
2837 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2838 .deviceId(mouseDeviceId)
2839 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2840 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2842 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002843 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2844
2845 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2847 .deviceId(touchDeviceId)
2848 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2849 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002850 leftWindow->assertNoEvents();
2851
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2853
2854 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002855 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2856 .deviceId(touchDeviceId)
2857 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2858 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2859 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002860 // Since this is now a new splittable pointer going down on the left window, and it's coming
2861 // from a different device, the current gesture in the left window (pointer down) should first
2862 // be canceled.
2863 leftWindow->consumeMotionEvent(
2864 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865 leftWindow->consumeMotionEvent(
2866 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2867 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2868 // current implementation.
2869 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2870 rightWindow->consumeMotionEvent(
2871 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2872
2873 leftWindow->assertNoEvents();
2874 rightWindow->assertNoEvents();
2875}
2876
2877/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002878 * Two windows: a window on the left and a window on the right.
2879 * Mouse is hovered on the left window and stylus is hovered on the right window.
2880 */
2881TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2883 sp<FakeWindowHandle> leftWindow =
2884 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2885 leftWindow->setFrame(Rect(0, 0, 200, 200));
2886
2887 sp<FakeWindowHandle> rightWindow =
2888 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2889 rightWindow->setFrame(Rect(200, 0, 400, 200));
2890
2891 mDispatcher->onWindowInfosChanged(
2892 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2893
2894 const int32_t stylusDeviceId = 3;
2895 const int32_t mouseDeviceId = 6;
2896
2897 // Start hovering over the left window
2898 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2899 .deviceId(mouseDeviceId)
2900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2901 .build());
2902 leftWindow->consumeMotionEvent(
2903 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2904
2905 // Stylus hovered on right window
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2907 .deviceId(stylusDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2909 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002910 rightWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2912
2913 // Subsequent HOVER_MOVE events are dispatched correctly.
2914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2915 .deviceId(mouseDeviceId)
2916 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2917 .build());
2918 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002919 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002920
2921 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2922 .deviceId(stylusDeviceId)
2923 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2924 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002926 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002927
2928 leftWindow->assertNoEvents();
2929 rightWindow->assertNoEvents();
2930}
2931
2932/**
2933 * Three windows: a window on the left and a window on the right.
2934 * And a spy window that's positioned above all of them.
2935 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2936 * Check the stream that's received by the spy.
2937 */
2938TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940
2941 sp<FakeWindowHandle> spyWindow =
2942 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2943 spyWindow->setFrame(Rect(0, 0, 400, 400));
2944 spyWindow->setTrustedOverlay(true);
2945 spyWindow->setSpy(true);
2946
2947 sp<FakeWindowHandle> leftWindow =
2948 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2949 leftWindow->setFrame(Rect(0, 0, 200, 200));
2950
2951 sp<FakeWindowHandle> rightWindow =
2952 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2953
2954 rightWindow->setFrame(Rect(200, 0, 400, 200));
2955
2956 mDispatcher->onWindowInfosChanged(
2957 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2958
2959 const int32_t stylusDeviceId = 1;
2960 const int32_t touchDeviceId = 2;
2961
2962 // Stylus down on the left window
2963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2964 .deviceId(stylusDeviceId)
2965 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2966 .build());
2967 leftWindow->consumeMotionEvent(
2968 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2969 spyWindow->consumeMotionEvent(
2970 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2971
2972 // Touch down on the right window
2973 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2974 .deviceId(touchDeviceId)
2975 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2976 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002977 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002978 rightWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002980
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002981 // Spy window does not receive touch events, because stylus events take precedence, and it
2982 // already has an active stylus gesture.
2983
2984 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2986 .deviceId(stylusDeviceId)
2987 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2988 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002989 leftWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2991 spyWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002994 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2996 .deviceId(touchDeviceId)
2997 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2998 .build());
2999 rightWindow->consumeMotionEvent(
3000 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001
3002 spyWindow->assertNoEvents();
3003 leftWindow->assertNoEvents();
3004 rightWindow->assertNoEvents();
3005}
3006
3007/**
3008 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3009 * both.
3010 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003011 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003012 * At the same time, left and right should be getting independent streams of hovering and touch,
3013 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003014 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003015TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003016 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3017
3018 sp<FakeWindowHandle> spyWindow =
3019 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3020 spyWindow->setFrame(Rect(0, 0, 400, 400));
3021 spyWindow->setTrustedOverlay(true);
3022 spyWindow->setSpy(true);
3023
3024 sp<FakeWindowHandle> leftWindow =
3025 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3026 leftWindow->setFrame(Rect(0, 0, 200, 200));
3027
3028 sp<FakeWindowHandle> rightWindow =
3029 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3030 rightWindow->setFrame(Rect(200, 0, 400, 200));
3031
3032 mDispatcher->onWindowInfosChanged(
3033 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3034
3035 const int32_t stylusDeviceId = 1;
3036 const int32_t touchDeviceId = 2;
3037
3038 // Stylus hover on the left window
3039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3040 .deviceId(stylusDeviceId)
3041 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3042 .build());
3043 leftWindow->consumeMotionEvent(
3044 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3045 spyWindow->consumeMotionEvent(
3046 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3047
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003048 // Touch down on the right window. Spy doesn't receive this touch because it already has
3049 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3051 .deviceId(touchDeviceId)
3052 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3053 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003054 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003055 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003056 rightWindow->consumeMotionEvent(
3057 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3058
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003059 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3061 .deviceId(stylusDeviceId)
3062 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3063 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003064 leftWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003066 spyWindow->consumeMotionEvent(
3067 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003069 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3071 .deviceId(touchDeviceId)
3072 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3073 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 rightWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3076
3077 spyWindow->assertNoEvents();
3078 leftWindow->assertNoEvents();
3079 rightWindow->assertNoEvents();
3080}
3081
3082/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003083 * On a single window, use two different devices: mouse and touch.
3084 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3085 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3086 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3087 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3088 * represent a new gesture.
3089 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003090TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3092 sp<FakeWindowHandle> window =
3093 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3094 window->setFrame(Rect(0, 0, 400, 400));
3095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003097
3098 const int32_t touchDeviceId = 4;
3099 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003101 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003102 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3110 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3114 .deviceId(touchDeviceId)
3115 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3116 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3117 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3119 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3120 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3121
3122 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3124 .deviceId(mouseDeviceId)
3125 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3127 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003128
3129 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003130 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003131 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3132
Prabir Pradhan678438e2023-04-13 19:32:51 +00003133 mDispatcher->notifyMotion(
3134 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3135 .deviceId(mouseDeviceId)
3136 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3137 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3139 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3141
3142 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003143 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3144 .deviceId(touchDeviceId)
3145 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3146 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3147 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003148 // Since we already canceled this touch gesture, it will be ignored until a completely new
3149 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3150 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3151 // However, mouse movements should continue to work.
3152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3153 .deviceId(mouseDeviceId)
3154 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3155 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3156 .build());
3157 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3158
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003159 window->assertNoEvents();
3160}
3161
3162/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003163 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3164 * the injected event.
3165 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003166TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3168 sp<FakeWindowHandle> window =
3169 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3170 window->setFrame(Rect(0, 0, 400, 400));
3171
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003172 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003173
3174 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003175 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3176 // completion.
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003178 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003179 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3180 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003181 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003182 .build()));
3183 window->consumeMotionEvent(
3184 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3185
3186 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3187 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3189 .deviceId(touchDeviceId)
3190 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3191 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003192
3193 window->consumeMotionEvent(
3194 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3195 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3196}
3197
3198/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003199 * This test is similar to the test above, but the sequence of injected events is different.
3200 *
3201 * Two windows: a window on the left and a window on the right.
3202 * Mouse is hovered over the left window.
3203 * Next, we tap on the left window, where the cursor was last seen.
3204 *
3205 * After that, we inject one finger down onto the right window, and then a second finger down onto
3206 * the left window.
3207 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3208 * window (first), and then another on the left window (second).
3209 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3210 * In the buggy implementation, second finger down on the left window would cause a crash.
3211 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003212TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3214 sp<FakeWindowHandle> leftWindow =
3215 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3216 leftWindow->setFrame(Rect(0, 0, 200, 200));
3217
3218 sp<FakeWindowHandle> rightWindow =
3219 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3220 rightWindow->setFrame(Rect(200, 0, 400, 200));
3221
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003222 mDispatcher->onWindowInfosChanged(
3223 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003224
3225 const int32_t mouseDeviceId = 6;
3226 const int32_t touchDeviceId = 4;
3227 // Hover over the left window. Keep the cursor there.
3228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003229 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003230 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3231 AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003233 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003234 .build()));
3235 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3236
3237 // Tap on left window
3238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003240 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3241 AINPUT_SOURCE_TOUCHSCREEN)
3242 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003243 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003244 .build()));
3245
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003248 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252 .build()));
3253 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3254 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3255 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3256
3257 // First finger down on right window
3258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003260 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3261 AINPUT_SOURCE_TOUCHSCREEN)
3262 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003263 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003264 .build()));
3265 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3266
3267 // Second finger down on the left window
3268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003269 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003270 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3271 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003272 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3273 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003274 .build()));
3275 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3276 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3277
3278 // No more events
3279 leftWindow->assertNoEvents();
3280 rightWindow->assertNoEvents();
3281}
3282
3283/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003284 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3285 * While the touch is down, new hover events from the stylus device should be ignored. After the
3286 * touch is gone, stylus hovering should start working again.
3287 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003288TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003289 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3290 sp<FakeWindowHandle> window =
3291 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3292 window->setFrame(Rect(0, 0, 200, 200));
3293
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003294 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003295
3296 const int32_t stylusDeviceId = 5;
3297 const int32_t touchDeviceId = 4;
3298 // Start hovering with stylus
3299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003300 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003301 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003302 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003303 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003304 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003305 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003306
3307 // Finger down on the window
3308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003309 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003310 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003311 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003314 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003315
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003316 // Continue hovering with stylus.
3317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003319 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3320 AINPUT_SOURCE_STYLUS)
3321 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003323 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003324 // Hovers continue to work
3325 window->consumeMotionEvent(
3326 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003327
3328 // Lift up the finger
3329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003330 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003331 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3332 AINPUT_SOURCE_TOUCHSCREEN)
3333 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003334 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003335 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003336
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003338 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3340 AINPUT_SOURCE_STYLUS)
3341 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003342 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003344 window->consumeMotionEvent(
3345 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003346 window->assertNoEvents();
3347}
3348
3349/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003350 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3351 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3352 *
3353 * Two windows: one on the left and one on the right.
3354 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3355 * Stylus down on the left window, and then touch down on the right window.
3356 * Check that the right window doesn't get touches while the stylus is down on the left window.
3357 */
3358TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3360 sp<FakeWindowHandle> leftWindow =
3361 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3362 ADISPLAY_ID_DEFAULT);
3363 leftWindow->setFrame(Rect(0, 0, 100, 100));
3364
3365 sp<FakeWindowHandle> sbtRightWindow =
3366 sp<FakeWindowHandle>::make(application, mDispatcher,
3367 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3368 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3369 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3370
3371 mDispatcher->onWindowInfosChanged(
3372 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3373
3374 const int32_t stylusDeviceId = 5;
3375 const int32_t touchDeviceId = 4;
3376
3377 // Stylus down in the left window
3378 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3379 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3380 .deviceId(stylusDeviceId)
3381 .build());
3382 leftWindow->consumeMotionEvent(
3383 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3384
3385 // Finger tap on the right window
3386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3387 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3388 .deviceId(touchDeviceId)
3389 .build());
3390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3391 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3392 .deviceId(touchDeviceId)
3393 .build());
3394
3395 // The touch should be blocked, because stylus is down somewhere else on screen!
3396 sbtRightWindow->assertNoEvents();
3397
3398 // Continue stylus motion, and ensure it's not impacted.
3399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3400 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3401 .deviceId(stylusDeviceId)
3402 .build());
3403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3405 .deviceId(stylusDeviceId)
3406 .build());
3407 leftWindow->consumeMotionEvent(
3408 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3409 leftWindow->consumeMotionEvent(
3410 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3411
3412 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3414 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3415 .deviceId(touchDeviceId)
3416 .build());
3417 sbtRightWindow->consumeMotionEvent(
3418 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3419}
3420
3421/**
3422 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3423 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3424 *
3425 * Two windows: one on the left and one on the right.
3426 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3427 * Stylus hover on the left window, and then touch down on the right window.
3428 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3429 */
3430TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3432 sp<FakeWindowHandle> leftWindow =
3433 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3434 ADISPLAY_ID_DEFAULT);
3435 leftWindow->setFrame(Rect(0, 0, 100, 100));
3436
3437 sp<FakeWindowHandle> sbtRightWindow =
3438 sp<FakeWindowHandle>::make(application, mDispatcher,
3439 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3440 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3441 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3442
3443 mDispatcher->onWindowInfosChanged(
3444 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3445
3446 const int32_t stylusDeviceId = 5;
3447 const int32_t touchDeviceId = 4;
3448
3449 // Stylus hover in the left window
3450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3451 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3452 .deviceId(stylusDeviceId)
3453 .build());
3454 leftWindow->consumeMotionEvent(
3455 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3456
3457 // Finger tap on the right window
3458 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3459 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3460 .deviceId(touchDeviceId)
3461 .build());
3462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3463 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3464 .deviceId(touchDeviceId)
3465 .build());
3466
3467 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3468 sbtRightWindow->assertNoEvents();
3469
3470 // Continue stylus motion, and ensure it's not impacted.
3471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3472 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3473 .deviceId(stylusDeviceId)
3474 .build());
3475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3476 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3477 .deviceId(stylusDeviceId)
3478 .build());
3479 leftWindow->consumeMotionEvent(
3480 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3481 leftWindow->consumeMotionEvent(
3482 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3483
3484 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3485 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3486 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3487 .deviceId(touchDeviceId)
3488 .build());
3489 sbtRightWindow->consumeMotionEvent(
3490 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3491}
3492
3493/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003494 * A spy window above a window with no input channel.
3495 * Start hovering with a stylus device, and then tap with it.
3496 * Ensure spy window receives the entire sequence.
3497 */
3498TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3500 sp<FakeWindowHandle> spyWindow =
3501 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3502 spyWindow->setFrame(Rect(0, 0, 200, 200));
3503 spyWindow->setTrustedOverlay(true);
3504 spyWindow->setSpy(true);
3505 sp<FakeWindowHandle> window =
3506 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3507 window->setNoInputChannel(true);
3508 window->setFrame(Rect(0, 0, 200, 200));
3509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003510 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003511
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003512 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3514 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003516 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3517 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3522
3523 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3525 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003527 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3528
3529 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003530 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3531 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3532 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003533 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3534
3535 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3538 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003539 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3540 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3542 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3543 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003544 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3545
3546 // No more events
3547 spyWindow->assertNoEvents();
3548 window->assertNoEvents();
3549}
3550
3551/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003552 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3553 * rejected. But since we already have an ongoing gesture, this event should be processed.
3554 * This prevents inconsistent events being handled inside the dispatcher.
3555 */
3556TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3558
3559 sp<FakeWindowHandle> window =
3560 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3561 window->setFrame(Rect(0, 0, 200, 200));
3562
3563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3564
3565 // Start hovering with stylus
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3568 .build());
3569 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3570
3571 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3572 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3573 .build();
3574 // Make this 'hoverExit' event stale
3575 mFakePolicy->setStaleEventTimeout(100ms);
3576 std::this_thread::sleep_for(100ms);
3577
3578 // It shouldn't be dropped by the dispatcher, even though it's stale.
3579 mDispatcher->notifyMotion(hoverExit);
3580 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3581
3582 // Stylus starts hovering again! There should be no crash.
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3585 .build());
3586 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3587}
3588
3589/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003590 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3591 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3592 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3593 * While the mouse is down, new move events from the touch device should be ignored.
3594 */
3595TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3597 sp<FakeWindowHandle> spyWindow =
3598 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3599 spyWindow->setFrame(Rect(0, 0, 200, 200));
3600 spyWindow->setTrustedOverlay(true);
3601 spyWindow->setSpy(true);
3602 sp<FakeWindowHandle> window =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3604 window->setFrame(Rect(0, 0, 200, 200));
3605
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003606 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003607
3608 const int32_t mouseDeviceId = 7;
3609 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003610
3611 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3613 .deviceId(mouseDeviceId)
3614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3615 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003616 spyWindow->consumeMotionEvent(
3617 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3618 window->consumeMotionEvent(
3619 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3620
3621 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3623 .deviceId(touchDeviceId)
3624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3625 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003626 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3627 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3628 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3629 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3630
Prabir Pradhan678438e2023-04-13 19:32:51 +00003631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3632 .deviceId(touchDeviceId)
3633 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3636 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3637
3638 // Pilfer the stream
3639 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3640 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3641
Prabir Pradhan678438e2023-04-13 19:32:51 +00003642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3643 .deviceId(touchDeviceId)
3644 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3645 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003646 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3647
3648 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3650 .deviceId(mouseDeviceId)
3651 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3652 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003654
3655 spyWindow->consumeMotionEvent(
3656 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3657 spyWindow->consumeMotionEvent(
3658 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3659 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3660
Prabir Pradhan678438e2023-04-13 19:32:51 +00003661 mDispatcher->notifyMotion(
3662 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3663 .deviceId(mouseDeviceId)
3664 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3665 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003668 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3669 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3670
3671 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3673 .deviceId(mouseDeviceId)
3674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003677 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3678 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3679
3680 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3682 .deviceId(touchDeviceId)
3683 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3684 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003685
3686 // No more events
3687 spyWindow->assertNoEvents();
3688 window->assertNoEvents();
3689}
3690
3691/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003692 * On the display, have a single window, and also an area where there's no window.
3693 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3694 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3695 */
3696TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3698 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003699 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003700
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003701 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003702
3703 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003704 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003705
3706 mDispatcher->waitForIdle();
3707 window->assertNoEvents();
3708
3709 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003710 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003711 mDispatcher->waitForIdle();
3712 window->consumeMotionDown();
3713}
3714
3715/**
3716 * Same test as above, but instead of touching the empty space, the first touch goes to
3717 * non-touchable window.
3718 */
3719TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3721 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003722 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003723 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3724 window1->setTouchable(false);
3725 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003727 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3728
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003729 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003730
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003731 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003732 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003733
3734 mDispatcher->waitForIdle();
3735 window1->assertNoEvents();
3736 window2->assertNoEvents();
3737
3738 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003740 mDispatcher->waitForIdle();
3741 window2->consumeMotionDown();
3742}
3743
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003744/**
3745 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3746 * to the event time of the first ACTION_DOWN sent to the particular window.
3747 */
3748TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3750 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003751 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003752 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3753 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003754 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003755 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003757 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003758
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003759 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003761
3762 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003763
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003764 const MotionEvent& motionEvent1 = window1->consumeMotionEvent();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003765 window2->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003766 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3767 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003768
3769 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003770 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003771 mDispatcher->waitForIdle();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003772 const MotionEvent& motionEvent2 = window2->consumeMotionEvent();
3773 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003774 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003775 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003776
3777 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003779 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003780 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003781
3782 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003783 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003784 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003785 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003786
3787 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3788 window1->consumeMotionMove();
3789 window1->assertNoEvents();
3790
3791 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003792 mDispatcher->notifyMotion(
3793 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003794 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003795 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003796
Prabir Pradhan678438e2023-04-13 19:32:51 +00003797 mDispatcher->notifyMotion(
3798 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003799 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003800 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003801}
3802
Garfield Tandf26e862020-07-01 20:18:19 -07003803TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003805 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003806 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003807 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003808 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003809 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003810 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003811
3812 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3813
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003814 mDispatcher->onWindowInfosChanged(
3815 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003816
3817 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003819 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003820 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3821 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003822 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003823 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003824 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003825
3826 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003828 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003829 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3830 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003831 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003832 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003833 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3834 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003835
3836 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003838 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003839 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3840 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003842 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003843 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3844 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003845
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003847 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003848 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3849 AINPUT_SOURCE_MOUSE)
3850 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3851 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003853 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003854 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003855
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003857 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003858 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3859 AINPUT_SOURCE_MOUSE)
3860 .buttonState(0)
3861 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003862 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003863 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003864 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003865
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003867 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003868 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3869 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003870 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003871 .build()));
3872 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3873
3874 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003876 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003877 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3878 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003879 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003880 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003881 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003882
3883 // No more events
3884 windowLeft->assertNoEvents();
3885 windowRight->assertNoEvents();
3886}
3887
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003888/**
3889 * Put two fingers down (and don't release them) and click the mouse button.
3890 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3891 * currently active gesture should be canceled, and the new one should proceed.
3892 */
3893TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3895 sp<FakeWindowHandle> window =
3896 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3897 window->setFrame(Rect(0, 0, 600, 800));
3898
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003899 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003900
3901 const int32_t touchDeviceId = 4;
3902 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003903
3904 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3906 .deviceId(touchDeviceId)
3907 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3908 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003909
Prabir Pradhan678438e2023-04-13 19:32:51 +00003910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3911 .deviceId(touchDeviceId)
3912 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3913 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3914 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003915 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3916 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3917
3918 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003919 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3920 .deviceId(mouseDeviceId)
3921 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3922 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3923 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003924 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3925 WithPointerCount(2u)));
3926 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3927
Prabir Pradhan678438e2023-04-13 19:32:51 +00003928 mDispatcher->notifyMotion(
3929 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3930 .deviceId(mouseDeviceId)
3931 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3932 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3934 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3936
3937 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3938 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003939 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3940 .deviceId(touchDeviceId)
3941 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3942 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3943 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003944 window->assertNoEvents();
3945}
3946
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003947TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3949
3950 sp<FakeWindowHandle> spyWindow =
3951 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3952 spyWindow->setFrame(Rect(0, 0, 600, 800));
3953 spyWindow->setTrustedOverlay(true);
3954 spyWindow->setSpy(true);
3955 sp<FakeWindowHandle> window =
3956 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3957 window->setFrame(Rect(0, 0, 600, 800));
3958
3959 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003960 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003961
3962 // Send mouse cursor to the window
3963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003965 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3966 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003968 .build()));
3969
3970 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3971 WithSource(AINPUT_SOURCE_MOUSE)));
3972 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3973 WithSource(AINPUT_SOURCE_MOUSE)));
3974
3975 window->assertNoEvents();
3976 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003977}
3978
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003979TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3981
3982 sp<FakeWindowHandle> spyWindow =
3983 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3984 spyWindow->setFrame(Rect(0, 0, 600, 800));
3985 spyWindow->setTrustedOverlay(true);
3986 spyWindow->setSpy(true);
3987 sp<FakeWindowHandle> window =
3988 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3989 window->setFrame(Rect(0, 0, 600, 800));
3990
3991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003992 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003993
3994 // Send mouse cursor to the window
3995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003996 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003997 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3998 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004000 .build()));
4001
4002 // Move mouse cursor
4003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004004 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004005 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4006 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004007 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004008 .build()));
4009
4010 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4011 WithSource(AINPUT_SOURCE_MOUSE)));
4012 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4013 WithSource(AINPUT_SOURCE_MOUSE)));
4014 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4015 WithSource(AINPUT_SOURCE_MOUSE)));
4016 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4017 WithSource(AINPUT_SOURCE_MOUSE)));
4018 // Touch down on the window
4019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004020 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004021 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4022 AINPUT_SOURCE_TOUCHSCREEN)
4023 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004024 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004025 .build()));
4026 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4027 WithSource(AINPUT_SOURCE_MOUSE)));
4028 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4029 WithSource(AINPUT_SOURCE_MOUSE)));
4030 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4031 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4032 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4033 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4034
4035 // pilfer the motion, retaining the gesture on the spy window.
4036 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4037 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4038 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4039
4040 // Touch UP on the window
4041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004042 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004043 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4044 AINPUT_SOURCE_TOUCHSCREEN)
4045 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004046 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004047 .build()));
4048 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4049 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4050
4051 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4052 // to send a new gesture. It should again go to both windows (spy and the window below), just
4053 // like the first gesture did, before pilfering. The window configuration has not changed.
4054
4055 // One more tap - DOWN
4056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004057 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004058 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4059 AINPUT_SOURCE_TOUCHSCREEN)
4060 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004061 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004062 .build()));
4063 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4064 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4065 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4066 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4067
4068 // Touch UP on the window
4069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004070 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004071 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4072 AINPUT_SOURCE_TOUCHSCREEN)
4073 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004074 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004075 .build()));
4076 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4077 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4078 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4079 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4080
4081 window->assertNoEvents();
4082 spyWindow->assertNoEvents();
4083}
4084
Garfield Tandf26e862020-07-01 20:18:19 -07004085// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4086// directly in this test.
4087TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004089 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004090 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004091 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004092
4093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4094
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004095 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004096
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004098 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004099 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4100 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004101 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004102 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004103 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004104 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004106 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004107 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4108 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004109 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004110 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004111 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004113
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004116 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4117 AINPUT_SOURCE_MOUSE)
4118 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4119 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004121 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004122 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004123
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004125 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004126 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4127 AINPUT_SOURCE_MOUSE)
4128 .buttonState(0)
4129 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004131 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004132 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004133
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004135 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004136 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4137 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004139 .build()));
4140 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4141
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004142 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4143 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4144 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004145 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004146 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4147 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004148 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004149 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004150 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004151}
4152
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004153/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004154 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4155 * is generated.
4156 */
4157TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4159 sp<FakeWindowHandle> window =
4160 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4161 window->setFrame(Rect(0, 0, 1200, 800));
4162
4163 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004166
4167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004168 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004169 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4170 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004171 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004172 .build()));
4173 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4174
4175 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004176 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004177 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4178}
4179
4180/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004181 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4182 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004183TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4184 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4185 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4187 sp<FakeWindowHandle> window =
4188 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4189 window->setFrame(Rect(0, 0, 1200, 800));
4190
4191 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4192
4193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4194
4195 MotionEventBuilder hoverEnterBuilder =
4196 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4197 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4198 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4200 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4202 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4203 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4204 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4205}
4206
4207/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004208 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4209 */
4210TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4212 sp<FakeWindowHandle> window =
4213 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4214 window->setFrame(Rect(0, 0, 100, 100));
4215
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004216 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004217
4218 const int32_t mouseDeviceId = 7;
4219 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004220
4221 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004222 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4223 .deviceId(mouseDeviceId)
4224 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4225 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004226 window->consumeMotionEvent(
4227 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4228
4229 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4231 .deviceId(touchDeviceId)
4232 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4233 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004234
4235 window->consumeMotionEvent(
4236 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4238}
4239
4240/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004241 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004242 * The tap causes a HOVER_EXIT event to be generated because the current event
4243 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004244 */
4245TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4247 sp<FakeWindowHandle> window =
4248 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4249 window->setFrame(Rect(0, 0, 100, 100));
4250
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004251 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004252 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4254 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004255 ASSERT_NO_FATAL_FAILURE(
4256 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4257 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004258
4259 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4261 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4262 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004263 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004264 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4265 WithSource(AINPUT_SOURCE_MOUSE))));
4266
4267 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004268 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4269 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4270
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4273 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004274 ASSERT_NO_FATAL_FAILURE(
4275 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4276 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4277}
4278
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004279TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4281 sp<FakeWindowHandle> windowDefaultDisplay =
4282 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4283 ADISPLAY_ID_DEFAULT);
4284 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4285 sp<FakeWindowHandle> windowSecondDisplay =
4286 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4287 SECOND_DISPLAY_ID);
4288 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4289
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004290 mDispatcher->onWindowInfosChanged(
4291 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004292
4293 // Set cursor position in window in default display and check that hover enter and move
4294 // events are generated.
4295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004296 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004297 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4298 AINPUT_SOURCE_MOUSE)
4299 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004300 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004301 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004302 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004303
4304 // Remove all windows in secondary display and check that no event happens on window in
4305 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004306 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4307
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004308 windowDefaultDisplay->assertNoEvents();
4309
4310 // Move cursor position in window in default display and check that only hover move
4311 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004312 mDispatcher->onWindowInfosChanged(
4313 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004315 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004316 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4317 AINPUT_SOURCE_MOUSE)
4318 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004320 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004321 windowDefaultDisplay->consumeMotionEvent(
4322 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4323 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004324 windowDefaultDisplay->assertNoEvents();
4325}
4326
Garfield Tan00f511d2019-06-12 16:55:40 -07004327TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004329
4330 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004332 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004333 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004334 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004335 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004336
4337 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4338
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004339 mDispatcher->onWindowInfosChanged(
4340 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004341
4342 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4343 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004345 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004346 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004347 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004348 windowRight->assertNoEvents();
4349}
4350
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004351TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004353 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4354 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004355 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004356
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004357 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004358 setFocusedWindow(window);
4359
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004360 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004361
Prabir Pradhan678438e2023-04-13 19:32:51 +00004362 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004363
4364 // Window should receive key down event.
4365 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4366
4367 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4368 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004369 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004370 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004371}
4372
4373TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004375 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4376 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004377
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004378 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004379
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4381 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004382
4383 // Window should receive motion down event.
4384 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4385
4386 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4387 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004388 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004389 window->consumeMotionEvent(
4390 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004391}
4392
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004393TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4396 "Fake Window", ADISPLAY_ID_DEFAULT);
4397
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004398 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004399
4400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4401 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4402 .build());
4403
4404 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4405
4406 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4407 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4408 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4409
4410 // After the device has been reset, a new hovering stream can be sent to the window
4411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4412 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4413 .build());
4414 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4415}
4416
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004417TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004419 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4420 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004421 window->setFocusable(true);
4422
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004423 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004424 setFocusedWindow(window);
4425
4426 window->consumeFocusEvent(true);
4427
Prabir Pradhan678438e2023-04-13 19:32:51 +00004428 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004429 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4430 const nsecs_t injectTime = keyArgs.eventTime;
4431 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004432 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004433 // The dispatching time should be always greater than or equal to intercept key timeout.
4434 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4435 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4436 std::chrono::nanoseconds(interceptKeyTimeout).count());
4437}
4438
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004439/**
4440 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4441 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004442TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004444 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4445 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004446 window->setFocusable(true);
4447
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004448 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004449 setFocusedWindow(window);
4450
4451 window->consumeFocusEvent(true);
4452
Prabir Pradhan678438e2023-04-13 19:32:51 +00004453 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004454 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004455
4456 // Set a value that's significantly larger than the default consumption timeout. If the
4457 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4458 mFakePolicy->setInterceptKeyTimeout(600ms);
4459 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4460 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004461 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4462}
4463
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004464/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004465 * Two windows. First is a regular window. Second does not overlap with the first, and has
4466 * WATCH_OUTSIDE_TOUCH.
4467 * Both windows are owned by the same UID.
4468 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4469 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4470 */
4471TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004473 sp<FakeWindowHandle> window =
4474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004475 window->setFrame(Rect{0, 0, 100, 100});
4476
4477 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004478 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004479 ADISPLAY_ID_DEFAULT);
4480 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4481 outsideWindow->setWatchOutsideTouch(true);
4482 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004483 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004484
4485 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004486 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4487 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4488 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004489 window->consumeMotionDown();
4490 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4491 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4492 outsideWindow->consumeMotionEvent(
4493 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004494
4495 // Ensure outsideWindow doesn't get any more events for the gesture.
4496 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4497 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4498 window->consumeMotionMove();
4499 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004500}
4501
4502/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004503 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4504 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4505 * ACTION_OUTSIDE event is sent per gesture.
4506 */
4507TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4508 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004510 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4511 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004512 window->setWatchOutsideTouch(true);
4513 window->setFrame(Rect{0, 0, 100, 100});
4514 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004515 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4516 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004517 secondWindow->setFrame(Rect{100, 100, 200, 200});
4518 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004519 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4520 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004521 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004522 mDispatcher->onWindowInfosChanged(
4523 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004524
4525 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4528 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004529 window->assertNoEvents();
4530 secondWindow->assertNoEvents();
4531
4532 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4533 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004534 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4535 ADISPLAY_ID_DEFAULT,
4536 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004537 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4538 window->consumeMotionEvent(
4539 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004540 secondWindow->consumeMotionDown();
4541 thirdWindow->assertNoEvents();
4542
4543 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4544 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004545 mDispatcher->notifyMotion(
4546 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4547 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004548 window->assertNoEvents();
4549 secondWindow->consumeMotionMove();
4550 thirdWindow->consumeMotionDown();
4551}
4552
Prabir Pradhan814fe082022-07-22 20:22:18 +00004553TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004555 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4556 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004557 window->setFocusable(true);
4558
Patrick Williamsd828f302023-04-28 17:52:08 -05004559 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004560 setFocusedWindow(window);
4561
4562 window->consumeFocusEvent(true);
4563
Prabir Pradhan678438e2023-04-13 19:32:51 +00004564 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4565 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4566 mDispatcher->notifyKey(keyDown);
4567 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004568
4569 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4570 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4571
4572 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004573 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004574
4575 window->consumeFocusEvent(false);
4576
Prabir Pradhan678438e2023-04-13 19:32:51 +00004577 mDispatcher->notifyKey(keyDown);
4578 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004579 window->assertNoEvents();
4580}
4581
Arthur Hung96483742022-11-15 03:30:48 +00004582TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4585 "Fake Window", ADISPLAY_ID_DEFAULT);
4586 // Ensure window is non-split and have some transform.
4587 window->setPreventSplitting(true);
4588 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004589 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004590
4591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004593 {50, 50}))
4594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4595 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4596
4597 const MotionEvent secondFingerDownEvent =
4598 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4599 .displayId(ADISPLAY_ID_DEFAULT)
4600 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004601 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4602 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004603 .build();
4604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004605 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004606 InputEventInjectionSync::WAIT_FOR_RESULT))
4607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4608
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004609 const MotionEvent& event = window->consumeMotionEvent();
4610 EXPECT_EQ(POINTER_1_DOWN, event.getAction());
4611 EXPECT_EQ(70, event.getX(0)); // 50 + 20
4612 EXPECT_EQ(90, event.getY(0)); // 50 + 40
4613 EXPECT_EQ(-10, event.getX(1)); // -30 + 20
4614 EXPECT_EQ(-10, event.getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004615}
4616
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004617/**
4618 * Two windows: a splittable and a non-splittable.
4619 * The non-splittable window shouldn't receive any "incomplete" gestures.
4620 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4621 * The second pointer should be dropped because the initial window is splittable, so it won't get
4622 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4623 * "incomplete" gestures.
4624 */
4625TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4627 sp<FakeWindowHandle> leftWindow =
4628 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4629 ADISPLAY_ID_DEFAULT);
4630 leftWindow->setPreventSplitting(false);
4631 leftWindow->setFrame(Rect(0, 0, 100, 100));
4632 sp<FakeWindowHandle> rightWindow =
4633 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4634 ADISPLAY_ID_DEFAULT);
4635 rightWindow->setPreventSplitting(true);
4636 rightWindow->setFrame(Rect(100, 100, 200, 200));
4637 mDispatcher->onWindowInfosChanged(
4638 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4639
4640 // Touch down on left, splittable window
4641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4642 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4643 .build());
4644 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4645
4646 mDispatcher->notifyMotion(
4647 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4648 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4649 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4650 .build());
4651 leftWindow->assertNoEvents();
4652 rightWindow->assertNoEvents();
4653}
4654
Harry Cuttsb166c002023-05-09 13:06:05 +00004655TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4657 sp<FakeWindowHandle> window =
4658 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4659 window->setFrame(Rect(0, 0, 400, 400));
4660 sp<FakeWindowHandle> trustedOverlay =
4661 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4662 ADISPLAY_ID_DEFAULT);
4663 trustedOverlay->setSpy(true);
4664 trustedOverlay->setTrustedOverlay(true);
4665
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004666 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004667
4668 // Start a three-finger touchpad swipe
4669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4670 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4671 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4672 .build());
4673 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4674 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4675 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4676 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4677 .build());
4678 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4679 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4680 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4681 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4682 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4683 .build());
4684
4685 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4686 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4687 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4688
4689 // Move the swipe a bit
4690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4691 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4692 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4693 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4694 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4695 .build());
4696
4697 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4698
4699 // End the swipe
4700 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4701 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4702 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4703 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4704 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4705 .build());
4706 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4707 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4708 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4709 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4710 .build());
4711 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4712 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4713 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4714 .build());
4715
4716 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4717 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4718 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4719
4720 window->assertNoEvents();
4721}
4722
4723TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4725 sp<FakeWindowHandle> window =
4726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4727 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004729
4730 // Start a three-finger touchpad swipe
4731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4732 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4733 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4734 .build());
4735 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4736 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4737 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4738 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4739 .build());
4740 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4741 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4742 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4743 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4744 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4745 .build());
4746
4747 // Move the swipe a bit
4748 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4749 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4750 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4751 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4752 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4753 .build());
4754
4755 // End the swipe
4756 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4757 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4758 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4759 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4760 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4761 .build());
4762 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4764 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4765 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4766 .build());
4767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4768 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4769 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4770 .build());
4771
4772 window->assertNoEvents();
4773}
4774
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004775/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004776 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4777 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004778 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004779 */
4780TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4782 sp<FakeWindowHandle> window =
4783 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4784 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004785 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004786
4787 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4789 .downTime(baseTime + 10)
4790 .eventTime(baseTime + 10)
4791 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4792 .build());
4793
4794 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4795
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004796 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004797 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004798
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004800
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004801 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4802 .downTime(baseTime + 10)
4803 .eventTime(baseTime + 30)
4804 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4805 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4806 .build());
4807
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004808 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4809
4810 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004811 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4812 .downTime(baseTime + 10)
4813 .eventTime(baseTime + 40)
4814 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4815 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4816 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004817
4818 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4819
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4821 .downTime(baseTime + 10)
4822 .eventTime(baseTime + 50)
4823 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4824 .build());
4825
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004826 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4827
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004828 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4829 .downTime(baseTime + 60)
4830 .eventTime(baseTime + 60)
4831 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4832 .build());
4833
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004834 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004835}
4836
4837/**
Hu Guo771a7692023-09-17 20:51:08 +08004838 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4839 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4840 * its coordinates should be converted by the transform of the windows of target screen.
4841 */
4842TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4843 // This case will create a window and a spy window on the default display and mirror
4844 // window on the second display. cancel event is sent through spy window pilferPointers
4845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4846
4847 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4848 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4849 spyWindowDefaultDisplay->setTrustedOverlay(true);
4850 spyWindowDefaultDisplay->setSpy(true);
4851
4852 sp<FakeWindowHandle> windowDefaultDisplay =
4853 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4854 ADISPLAY_ID_DEFAULT);
4855 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4856
4857 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4858 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4859
4860 // Add the windows to the dispatcher
4861 mDispatcher->onWindowInfosChanged(
4862 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4863 *windowSecondDisplay->getInfo()},
4864 {},
4865 0,
4866 0});
4867
4868 // Send down to ADISPLAY_ID_DEFAULT
4869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4870 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4871 {100, 100}))
4872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4873
4874 spyWindowDefaultDisplay->consumeMotionDown();
4875 windowDefaultDisplay->consumeMotionDown();
4876
4877 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4878
4879 // windowDefaultDisplay gets cancel
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004880 const MotionEvent& event = windowDefaultDisplay->consumeMotionEvent();
4881 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004882
4883 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4884 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4885 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4886 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004887 EXPECT_EQ(100, event.getX(0));
4888 EXPECT_EQ(100, event.getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004889}
4890
4891/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004892 * Ensure the correct coordinate spaces are used by InputDispatcher.
4893 *
4894 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4895 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4896 * space.
4897 */
4898class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4899public:
4900 void SetUp() override {
4901 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004902 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004903 }
4904
4905 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4906 gui::DisplayInfo info;
4907 info.displayId = displayId;
4908 info.transform = transform;
4909 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004910 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004911 }
4912
4913 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4914 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004915 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004916 }
4917
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004918 void removeAllWindowsAndDisplays() {
4919 mDisplayInfos.clear();
4920 mWindowInfos.clear();
4921 }
4922
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004923 // Set up a test scenario where the display has a scaled projection and there are two windows
4924 // on the display.
4925 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4926 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4927 // respectively.
4928 ui::Transform displayTransform;
4929 displayTransform.set(2, 0, 0, 4);
4930 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4931
4932 std::shared_ptr<FakeApplicationHandle> application =
4933 std::make_shared<FakeApplicationHandle>();
4934
4935 // Add two windows to the display. Their frames are represented in the display space.
4936 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004937 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4938 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004939 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4940 addWindow(firstWindow);
4941
4942 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004943 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4944 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004945 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4946 addWindow(secondWindow);
4947 return {std::move(firstWindow), std::move(secondWindow)};
4948 }
4949
4950private:
4951 std::vector<gui::DisplayInfo> mDisplayInfos;
4952 std::vector<gui::WindowInfo> mWindowInfos;
4953};
4954
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004955TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004956 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4957 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004958 // selected so that if the hit test was performed with the point and the bounds being in
4959 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004960 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4961 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4962 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004963
4964 firstWindow->consumeMotionDown();
4965 secondWindow->assertNoEvents();
4966}
4967
4968// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4969// the event should be treated as being in the logical display space.
4970TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4971 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4972 // Send down to the first window. The point is represented in the logical display space. The
4973 // point is selected so that if the hit test was done in logical display space, then it would
4974 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004976 PointF{75 * 2, 55 * 4});
4977
4978 firstWindow->consumeMotionDown();
4979 secondWindow->assertNoEvents();
4980}
4981
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004982// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4983// event should be treated as being in the logical display space.
4984TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4985 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4986
4987 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4988 ui::Transform injectedEventTransform;
4989 injectedEventTransform.set(matrix);
4990 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4991 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4992
4993 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4994 .displayId(ADISPLAY_ID_DEFAULT)
4995 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004996 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004997 .x(untransformedPoint.x)
4998 .y(untransformedPoint.y))
4999 .build();
5000 event.transform(matrix);
5001
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005002 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005003 InputEventInjectionSync::WAIT_FOR_RESULT);
5004
5005 firstWindow->consumeMotionDown();
5006 secondWindow->assertNoEvents();
5007}
5008
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005009TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5010 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5011
5012 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005013 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5015 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005016
5017 firstWindow->assertNoEvents();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005018 const MotionEvent& event = secondWindow->consumeMotionEvent();
5019 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event.getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005020
5021 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005022 EXPECT_EQ(300, event.getRawX(0));
5023 EXPECT_EQ(880, event.getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005024
5025 // Ensure that the x and y values are in the window's coordinate space.
5026 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5027 // the logical display space. This will be the origin of the window space.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00005028 EXPECT_EQ(100, event.getX(0));
5029 EXPECT_EQ(80, event.getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005030}
5031
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005032TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5033 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5034 // The monitor will always receive events in the logical display's coordinate space, because
5035 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005036 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005037
5038 // Send down to the first window.
5039 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5040 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5041 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5042 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5043
5044 // Second pointer goes down on second window.
5045 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5046 ADISPLAY_ID_DEFAULT,
5047 {PointF{50, 100}, PointF{150, 220}}));
5048 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5049 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5050 {1, PointF{300, 880}}};
5051 monitor.consumeMotionEvent(
5052 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5053
5054 mDispatcher->cancelCurrentTouch();
5055
5056 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5057 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5058 monitor.consumeMotionEvent(
5059 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5060}
5061
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005062TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5063 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5064
5065 // Send down to the first window.
5066 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5067 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5068 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5069
5070 // The pointer is transferred to the second window, and the second window receives it in the
5071 // correct coordinate space.
5072 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5073 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5074 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5075}
5076
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005077TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5078 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5079
5080 // Send hover move to the second window, and ensure it shows up as hover enter.
5081 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5082 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5083 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5084 WithCoords(100, 80), WithRawCoords(300, 880)));
5085
5086 // Touch down at the same location and ensure a hover exit is synthesized.
5087 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5088 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5089 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5090 WithRawCoords(300, 880)));
5091 secondWindow->consumeMotionEvent(
5092 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5093 secondWindow->assertNoEvents();
5094 firstWindow->assertNoEvents();
5095}
5096
Prabir Pradhan453ae732023-10-13 14:30:14 +00005097// Same as above, but while the window is being mirrored.
5098TEST_F(InputDispatcherDisplayProjectionTest,
5099 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5100 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5101
5102 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5103 ui::Transform secondDisplayTransform;
5104 secondDisplayTransform.set(matrix);
5105 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5106
5107 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5108 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5109 addWindow(secondWindowClone);
5110
5111 // Send hover move to the second window, and ensure it shows up as hover enter.
5112 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5113 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5114 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5115 WithCoords(100, 80), WithRawCoords(300, 880)));
5116
5117 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5118 // display.
5119 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5120 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5121 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5122 WithRawCoords(300, 880)));
5123 secondWindow->consumeMotionEvent(
5124 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5125 secondWindow->assertNoEvents();
5126 firstWindow->assertNoEvents();
5127}
5128
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005129TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5130 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5131
5132 // Send hover enter to second window
5133 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5134 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5135 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5136 WithCoords(100, 80), WithRawCoords(300, 880)));
5137
5138 mDispatcher->cancelCurrentTouch();
5139
5140 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5141 WithRawCoords(300, 880)));
5142 secondWindow->assertNoEvents();
5143 firstWindow->assertNoEvents();
5144}
5145
Prabir Pradhan453ae732023-10-13 14:30:14 +00005146// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005147TEST_F(InputDispatcherDisplayProjectionTest,
5148 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5149 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5150
5151 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5152 ui::Transform secondDisplayTransform;
5153 secondDisplayTransform.set(matrix);
5154 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5155
5156 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5157 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5158 addWindow(secondWindowClone);
5159
5160 // Send hover enter to second window
5161 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5162 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5163 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5164 WithCoords(100, 80), WithRawCoords(300, 880),
5165 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5166
5167 mDispatcher->cancelCurrentTouch();
5168
5169 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5170 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5171 WithRawCoords(300, 880),
5172 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5173 secondWindow->assertNoEvents();
5174 firstWindow->assertNoEvents();
5175}
5176
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005177/** Ensure consistent behavior of InputDispatcher in all orientations. */
5178class InputDispatcherDisplayOrientationFixture
5179 : public InputDispatcherDisplayProjectionTest,
5180 public ::testing::WithParamInterface<ui::Rotation> {};
5181
5182// This test verifies the touchable region of a window for all rotations of the display by tapping
5183// in different locations on the display, specifically points close to the four corners of a
5184// window.
5185TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5186 constexpr static int32_t displayWidth = 400;
5187 constexpr static int32_t displayHeight = 800;
5188
5189 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5190
5191 const auto rotation = GetParam();
5192
5193 // Set up the display with the specified rotation.
5194 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5195 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5196 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5197 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5198 logicalDisplayWidth, logicalDisplayHeight);
5199 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5200
5201 // Create a window with its bounds determined in the logical display.
5202 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5203 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5204 sp<FakeWindowHandle> window =
5205 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5206 window->setFrame(frameInDisplay, displayTransform);
5207 addWindow(window);
5208
5209 // The following points in logical display space should be inside the window.
5210 static const std::array<vec2, 4> insidePoints{
5211 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5212 for (const auto pointInsideWindow : insidePoints) {
5213 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5214 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005215 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5216 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5217 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005218 window->consumeMotionDown();
5219
Prabir Pradhan678438e2023-04-13 19:32:51 +00005220 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5221 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5222 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005223 window->consumeMotionUp();
5224 }
5225
5226 // The following points in logical display space should be outside the window.
5227 static const std::array<vec2, 5> outsidePoints{
5228 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5229 for (const auto pointOutsideWindow : outsidePoints) {
5230 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5231 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005232 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5233 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5234 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005235
Prabir Pradhan678438e2023-04-13 19:32:51 +00005236 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5237 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5238 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005239 }
5240 window->assertNoEvents();
5241}
5242
5243// Run the precision tests for all rotations.
5244INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5245 InputDispatcherDisplayOrientationFixture,
5246 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5247 ui::ROTATION_270),
5248 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5249 return ftl::enum_string(testParamInfo.param);
5250 });
5251
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005252using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5253 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005254
5255class TransferTouchFixture : public InputDispatcherTest,
5256 public ::testing::WithParamInterface<TransferFunction> {};
5257
5258TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005259 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005260
5261 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005262 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005263 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5264 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005265 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005266 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005267 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5268 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005269 sp<FakeWindowHandle> wallpaper =
5270 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5271 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005272 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005273 mDispatcher->onWindowInfosChanged(
5274 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005275
5276 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005277 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5278 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005279
Svet Ganov5d3bc372020-01-26 23:11:07 -08005280 // Only the first window should get the down event
5281 firstWindow->consumeMotionDown();
5282 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005284
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005285 // Transfer touch to the second window
5286 TransferFunction f = GetParam();
5287 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5288 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005289 // The first window gets cancel and the second gets down
5290 firstWindow->consumeMotionCancel();
5291 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005292 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005293
5294 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5296 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005297 // The first window gets no events and the second gets up
5298 firstWindow->assertNoEvents();
5299 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005300 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005301}
5302
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005303/**
5304 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5305 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5306 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5307 * natural to the user.
5308 * In this test, we are sending a pointer to both spy window and first window. We then try to
5309 * transfer touch to the second window. The dispatcher should identify the first window as the
5310 * one that should lose the gesture, and therefore the action should be to move the gesture from
5311 * the first window to the second.
5312 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5313 * the other API, as well.
5314 */
5315TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5317
5318 // Create a couple of windows + a spy window
5319 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005320 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005321 spyWindow->setTrustedOverlay(true);
5322 spyWindow->setSpy(true);
5323 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005324 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005325 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005327
5328 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005329 mDispatcher->onWindowInfosChanged(
5330 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005331
5332 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005333 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5334 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005335 // Only the first window and spy should get the down event
5336 spyWindow->consumeMotionDown();
5337 firstWindow->consumeMotionDown();
5338
5339 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5340 // if f === 'transferTouch'.
5341 TransferFunction f = GetParam();
5342 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5343 ASSERT_TRUE(success);
5344 // The first window gets cancel and the second gets down
5345 firstWindow->consumeMotionCancel();
5346 secondWindow->consumeMotionDown();
5347
5348 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5350 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005351 // The first window gets no events and the second+spy get up
5352 firstWindow->assertNoEvents();
5353 spyWindow->consumeMotionUp();
5354 secondWindow->consumeMotionUp();
5355}
5356
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005357TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005359
5360 PointF touchPoint = {10, 10};
5361
5362 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005363 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005364 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5365 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005366 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005367 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005368 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5369 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005370 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371
5372 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005373 mDispatcher->onWindowInfosChanged(
5374 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005375
5376 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005377 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5378 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5379 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005380 // Only the first window should get the down event
5381 firstWindow->consumeMotionDown();
5382 secondWindow->assertNoEvents();
5383
5384 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005385 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5386 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005387 // Only the first window should get the pointer down event
5388 firstWindow->consumeMotionPointerDown(1);
5389 secondWindow->assertNoEvents();
5390
5391 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005392 TransferFunction f = GetParam();
5393 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5394 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005395 // The first window gets cancel and the second gets down and pointer down
5396 firstWindow->consumeMotionCancel();
5397 secondWindow->consumeMotionDown();
5398 secondWindow->consumeMotionPointerDown(1);
5399
5400 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005401 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5402 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005403 // The first window gets nothing and the second gets pointer up
5404 firstWindow->assertNoEvents();
5405 secondWindow->consumeMotionPointerUp(1);
5406
5407 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5409 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005410 // The first window gets nothing and the second gets up
5411 firstWindow->assertNoEvents();
5412 secondWindow->consumeMotionUp();
5413}
5414
Arthur Hungc539dbb2022-12-08 07:45:36 +00005415TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5417
5418 // Create a couple of windows
5419 sp<FakeWindowHandle> firstWindow =
5420 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5421 ADISPLAY_ID_DEFAULT);
5422 firstWindow->setDupTouchToWallpaper(true);
5423 sp<FakeWindowHandle> secondWindow =
5424 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5425 ADISPLAY_ID_DEFAULT);
5426 secondWindow->setDupTouchToWallpaper(true);
5427
5428 sp<FakeWindowHandle> wallpaper1 =
5429 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5430 wallpaper1->setIsWallpaper(true);
5431
5432 sp<FakeWindowHandle> wallpaper2 =
5433 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5434 wallpaper2->setIsWallpaper(true);
5435 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005436 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5437 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5438 {},
5439 0,
5440 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005441
5442 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5444 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005445
5446 // Only the first window should get the down event
5447 firstWindow->consumeMotionDown();
5448 secondWindow->assertNoEvents();
5449 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5450 wallpaper2->assertNoEvents();
5451
5452 // Transfer touch focus to the second window
5453 TransferFunction f = GetParam();
5454 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5455 ASSERT_TRUE(success);
5456
5457 // The first window gets cancel and the second gets down
5458 firstWindow->consumeMotionCancel();
5459 secondWindow->consumeMotionDown();
5460 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5461 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5462
5463 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5465 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005466 // The first window gets no events and the second gets up
5467 firstWindow->assertNoEvents();
5468 secondWindow->consumeMotionUp();
5469 wallpaper1->assertNoEvents();
5470 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5471}
5472
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005473// For the cases of single pointer touch and two pointers non-split touch, the api's
5474// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5475// for the case where there are multiple pointers split across several windows.
5476INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5477 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005478 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5479 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005480 return dispatcher->transferTouch(destChannelToken,
5481 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005482 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005483 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5484 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005485 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005486 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005487 }));
5488
Svet Ganov5d3bc372020-01-26 23:11:07 -08005489TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005491
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005492 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005493 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5494 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005495 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005496
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005497 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005498 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5499 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005500 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005501
5502 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005503 mDispatcher->onWindowInfosChanged(
5504 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005505
5506 PointF pointInFirst = {300, 200};
5507 PointF pointInSecond = {300, 600};
5508
5509 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005510 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5511 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5512 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005513 // Only the first window should get the down event
5514 firstWindow->consumeMotionDown();
5515 secondWindow->assertNoEvents();
5516
5517 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005518 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5519 ADISPLAY_ID_DEFAULT,
5520 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005521 // The first window gets a move and the second a down
5522 firstWindow->consumeMotionMove();
5523 secondWindow->consumeMotionDown();
5524
5525 // Transfer touch focus to the second window
5526 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5527 // The first window gets cancel and the new gets pointer down (it already saw down)
5528 firstWindow->consumeMotionCancel();
5529 secondWindow->consumeMotionPointerDown(1);
5530
5531 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005532 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5533 ADISPLAY_ID_DEFAULT,
5534 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005535 // The first window gets nothing and the second gets pointer up
5536 firstWindow->assertNoEvents();
5537 secondWindow->consumeMotionPointerUp(1);
5538
5539 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005540 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5541 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005542 // The first window gets nothing and the second gets up
5543 firstWindow->assertNoEvents();
5544 secondWindow->consumeMotionUp();
5545}
5546
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005547// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5548// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5549// touch is not supported, so the touch should continue on those windows and the transferred-to
5550// window should get nothing.
5551TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5553
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005554 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005555 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5556 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005557 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005558
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005559 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005560 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5561 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005562 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005563
5564 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005565 mDispatcher->onWindowInfosChanged(
5566 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005567
5568 PointF pointInFirst = {300, 200};
5569 PointF pointInSecond = {300, 600};
5570
5571 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005572 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5573 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5574 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005575 // Only the first window should get the down event
5576 firstWindow->consumeMotionDown();
5577 secondWindow->assertNoEvents();
5578
5579 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005580 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5581 ADISPLAY_ID_DEFAULT,
5582 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005583 // The first window gets a move and the second a down
5584 firstWindow->consumeMotionMove();
5585 secondWindow->consumeMotionDown();
5586
5587 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005588 const bool transferred =
5589 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005590 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5591 ASSERT_FALSE(transferred);
5592 firstWindow->assertNoEvents();
5593 secondWindow->assertNoEvents();
5594
5595 // The rest of the dispatch should proceed as normal
5596 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005597 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5598 ADISPLAY_ID_DEFAULT,
5599 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005600 // The first window gets MOVE and the second gets pointer up
5601 firstWindow->consumeMotionMove();
5602 secondWindow->consumeMotionUp();
5603
5604 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005605 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5606 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005607 // The first window gets nothing and the second gets up
5608 firstWindow->consumeMotionUp();
5609 secondWindow->assertNoEvents();
5610}
5611
Arthur Hungabbb9d82021-09-01 14:52:30 +00005612// This case will create two windows and one mirrored window on the default display and mirror
5613// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5614// the windows info of second display before default display.
5615TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5617 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005618 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005619 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005620 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005621 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005622 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005623
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005624 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005625 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005626
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005627 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005628 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005629
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005630 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005631 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005632
5633 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005634 mDispatcher->onWindowInfosChanged(
5635 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5636 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5637 *secondWindowInPrimary->getInfo()},
5638 {},
5639 0,
5640 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005641
5642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005643 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005644 {50, 50}))
5645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5646
5647 // Window should receive motion event.
5648 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5649
5650 // Transfer touch focus
5651 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5652 secondWindowInPrimary->getToken()));
5653 // The first window gets cancel.
5654 firstWindowInPrimary->consumeMotionCancel();
5655 secondWindowInPrimary->consumeMotionDown();
5656
5657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005659 ADISPLAY_ID_DEFAULT, {150, 50}))
5660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5661 firstWindowInPrimary->assertNoEvents();
5662 secondWindowInPrimary->consumeMotionMove();
5663
5664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005665 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005666 {150, 50}))
5667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5668 firstWindowInPrimary->assertNoEvents();
5669 secondWindowInPrimary->consumeMotionUp();
5670}
5671
5672// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5673// 'transferTouch' api.
5674TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5676 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005677 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005678 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005679 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005680 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005681 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005682
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005683 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005684 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005685
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005686 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005687 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005688
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005689 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005690 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005691
5692 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005693 mDispatcher->onWindowInfosChanged(
5694 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5695 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5696 *secondWindowInPrimary->getInfo()},
5697 {},
5698 0,
5699 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005700
5701 // Touch on second display.
5702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005703 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5704 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5706
5707 // Window should receive motion event.
5708 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5709
5710 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005711 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005712
5713 // The first window gets cancel.
5714 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5715 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5716
5717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005718 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005719 SECOND_DISPLAY_ID, {150, 50}))
5720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5721 firstWindowInPrimary->assertNoEvents();
5722 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5723
5724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005725 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5727 firstWindowInPrimary->assertNoEvents();
5728 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5729}
5730
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005731TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5734 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005735
Vishnu Nair47074b82020-08-14 11:54:47 -07005736 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005738 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005739
5740 window->consumeFocusEvent(true);
5741
Prabir Pradhan678438e2023-04-13 19:32:51 +00005742 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005743
5744 // Window should receive key down event.
5745 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005746
5747 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005748 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005749 mFakePolicy->assertUserActivityPoked();
5750}
5751
5752TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5755 "Fake Window", ADISPLAY_ID_DEFAULT);
5756
5757 window->setDisableUserActivity(true);
5758 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005760 setFocusedWindow(window);
5761
5762 window->consumeFocusEvent(true);
5763
5764 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5765
5766 // Window should receive key down event.
5767 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5768
5769 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005770 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005771 mFakePolicy->assertUserActivityNotPoked();
5772}
5773
5774TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5776 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5777 "Fake Window", ADISPLAY_ID_DEFAULT);
5778
5779 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005781 setFocusedWindow(window);
5782
5783 window->consumeFocusEvent(true);
5784
5785 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5786 mDispatcher->waitForIdle();
5787
5788 // System key is not passed down
5789 window->assertNoEvents();
5790
5791 // Should have poked user activity
5792 mFakePolicy->assertUserActivityPoked();
5793}
5794
5795TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5798 "Fake Window", ADISPLAY_ID_DEFAULT);
5799
5800 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005802 setFocusedWindow(window);
5803
5804 window->consumeFocusEvent(true);
5805
5806 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5807 mDispatcher->waitForIdle();
5808
5809 // System key is not passed down
5810 window->assertNoEvents();
5811
5812 // Should have poked user activity
5813 mFakePolicy->assertUserActivityPoked();
5814}
5815
5816TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5818 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5819 "Fake Window", ADISPLAY_ID_DEFAULT);
5820
5821 window->setDisableUserActivity(true);
5822 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005824 setFocusedWindow(window);
5825
5826 window->consumeFocusEvent(true);
5827
5828 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5829 mDispatcher->waitForIdle();
5830
5831 // System key is not passed down
5832 window->assertNoEvents();
5833
5834 // Should have poked user activity
5835 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005836}
5837
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005838TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5840 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5841 "Fake Window", ADISPLAY_ID_DEFAULT);
5842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005844
5845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005846 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005847 ADISPLAY_ID_DEFAULT, {100, 100}))
5848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5849
5850 window->consumeMotionEvent(
5851 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5852
5853 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005854 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005855 mFakePolicy->assertUserActivityPoked();
5856}
5857
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005858TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005860 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5861 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005863 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005864
Prabir Pradhan678438e2023-04-13 19:32:51 +00005865 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005866 mDispatcher->waitForIdle();
5867
5868 window->assertNoEvents();
5869}
5870
5871// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5872TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5875 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005878
5879 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005880 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005881 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005882 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5883 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005884
5885 // Window should receive only the motion event
5886 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5887 window->assertNoEvents(); // Key event or focus event will not be received
5888}
5889
arthurhungea3f4fc2020-12-21 23:18:53 +08005890TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5892
arthurhungea3f4fc2020-12-21 23:18:53 +08005893 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005894 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5895 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005896 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005897
arthurhungea3f4fc2020-12-21 23:18:53 +08005898 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005899 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5900 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005901 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005902
5903 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005904 mDispatcher->onWindowInfosChanged(
5905 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005906
5907 PointF pointInFirst = {300, 200};
5908 PointF pointInSecond = {300, 600};
5909
5910 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005911 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5912 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5913 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005914 // Only the first window should get the down event
5915 firstWindow->consumeMotionDown();
5916 secondWindow->assertNoEvents();
5917
5918 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005919 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5920 ADISPLAY_ID_DEFAULT,
5921 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005922 // The first window gets a move and the second a down
5923 firstWindow->consumeMotionMove();
5924 secondWindow->consumeMotionDown();
5925
5926 // Send pointer cancel to the second window
5927 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005928 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005929 {pointInFirst, pointInSecond});
5930 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005931 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005932 // The first window gets move and the second gets cancel.
5933 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5934 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5935
5936 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005937 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5938 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005939 // The first window gets up and the second gets nothing.
5940 firstWindow->consumeMotionUp();
5941 secondWindow->assertNoEvents();
5942}
5943
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005944TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5946
5947 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005948 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005949 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005950 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5951 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5952 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5953
Harry Cutts33476232023-01-30 19:57:29 +00005954 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005955 window->assertNoEvents();
5956 mDispatcher->waitForIdle();
5957}
5958
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005959using InputDispatcherMonitorTest = InputDispatcherTest;
5960
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005961/**
5962 * Two entities that receive touch: A window, and a global monitor.
5963 * The touch goes to the window, and then the window disappears.
5964 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5965 * for the monitor, as well.
5966 * 1. foregroundWindow
5967 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5968 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005969TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005970 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5971 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005972 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005973
Prabir Pradhanfb549072023-10-05 19:17:36 +00005974 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005975
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005976 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005979 {100, 200}))
5980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5981
5982 // Both the foreground window and the global monitor should receive the touch down
5983 window->consumeMotionDown();
5984 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5985
5986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005987 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005988 ADISPLAY_ID_DEFAULT, {110, 200}))
5989 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5990
5991 window->consumeMotionMove();
5992 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5993
5994 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005995 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005996 window->consumeMotionCancel();
5997 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5998
5999 // If more events come in, there will be no more foreground window to send them to. This will
6000 // cause a cancel for the monitor, as well.
6001 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006002 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006003 ADISPLAY_ID_DEFAULT, {120, 200}))
6004 << "Injection should fail because the window was removed";
6005 window->assertNoEvents();
6006 // Global monitor now gets the cancel
6007 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6008}
6009
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006010TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006012 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6013 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006014 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006015
Prabir Pradhanfb549072023-10-05 19:17:36 +00006016 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006017
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006019 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006021 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006022 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006023}
6024
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006025TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006026 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006027
Chris Yea209fde2020-07-22 13:54:51 -07006028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006029 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6030 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006031 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006032
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006034 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006036 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006037 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006038
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006039 // Pilfer pointers from the monitor.
6040 // This should not do anything and the window should continue to receive events.
6041 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006042
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006044 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006045 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006046 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006047
6048 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6049 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006050}
6051
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006052TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006054 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6055 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006056 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006057 window->setWindowOffset(20, 40);
6058 window->setWindowTransform(0, 1, -1, 0);
6059
Prabir Pradhanfb549072023-10-05 19:17:36 +00006060 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006061
6062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006063 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6065 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6066 MotionEvent* event = monitor.consumeMotion();
6067 // Even though window has transform, gesture monitor must not.
6068 ASSERT_EQ(ui::Transform(), event->getTransform());
6069}
6070
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006071TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006072 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006073 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006075 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006076 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006077 << "Injection should fail if there is a monitor, but no touchable window";
6078 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006079}
6080
chaviw81e2bb92019-12-18 15:03:51 -08006081TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006083 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6084 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006085
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006086 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006087
6088 NotifyMotionArgs motionArgs =
6089 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6090 ADISPLAY_ID_DEFAULT);
6091
Prabir Pradhan678438e2023-04-13 19:32:51 +00006092 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006093 // Window should receive motion down event.
6094 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6095
6096 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006097 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006098 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6099 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6100 motionArgs.pointerCoords[0].getX() - 10);
6101
Prabir Pradhan678438e2023-04-13 19:32:51 +00006102 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006103 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006104}
6105
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006106/**
6107 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6108 * the device default right away. In the test scenario, we check both the default value,
6109 * and the action of enabling / disabling.
6110 */
6111TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006113 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6114 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006115 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006116
6117 // Set focused application.
6118 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006119 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006120
6121 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006122 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006123 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006124 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006125
6126 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006127 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006128 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006129 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006130
6131 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006132 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006133 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006134 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006135 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006136 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006137 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006138 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006139
6140 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006141 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006143 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006144
6145 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006146 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006147 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006148 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006149 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006150 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006151 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006152 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006153
6154 window->assertNoEvents();
6155}
6156
Gang Wange9087892020-01-07 12:17:14 -05006157TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006159 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6160 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006161
6162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006163 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006166 setFocusedWindow(window);
6167
Harry Cutts33476232023-01-30 19:57:29 +00006168 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006169
Prabir Pradhan678438e2023-04-13 19:32:51 +00006170 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6171 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006172
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006173 const KeyEvent& event = window->consumeKey();
Gang Wange9087892020-01-07 12:17:14 -05006174
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006175 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Gang Wange9087892020-01-07 12:17:14 -05006176 ASSERT_NE(verified, nullptr);
6177 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6178
6179 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6180 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6181 ASSERT_EQ(keyArgs.source, verified->source);
6182 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6183
6184 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6185
6186 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006187 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006188 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006189 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6190 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6191 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6192 ASSERT_EQ(0, verifiedKey.repeatCount);
6193}
6194
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006195TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006197 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6198 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006199
6200 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6201
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006202 ui::Transform transform;
6203 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6204
6205 gui::DisplayInfo displayInfo;
6206 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6207 displayInfo.transform = transform;
6208
Patrick Williamsd828f302023-04-28 17:52:08 -05006209 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006210
Prabir Pradhan678438e2023-04-13 19:32:51 +00006211 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006212 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6213 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006214 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006215
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006216 const MotionEvent& event = window->consumeMotionEvent();
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006217
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006218 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006219 ASSERT_NE(verified, nullptr);
6220 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6221
6222 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6223 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6224 EXPECT_EQ(motionArgs.source, verified->source);
6225 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6226
6227 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6228
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006229 const vec2 rawXY =
6230 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6231 motionArgs.pointerCoords[0].getXYValue());
6232 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6233 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006234 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006235 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006236 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006237 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6238 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6239}
6240
chaviw09c8d2d2020-08-24 15:48:26 -07006241/**
6242 * Ensure that separate calls to sign the same data are generating the same key.
6243 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6244 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6245 * tests.
6246 */
6247TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6248 KeyEvent event = getTestKeyEvent();
6249 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6250
6251 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6252 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6253 ASSERT_EQ(hmac1, hmac2);
6254}
6255
6256/**
6257 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6258 */
6259TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6260 KeyEvent event = getTestKeyEvent();
6261 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6262 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6263
6264 verifiedEvent.deviceId += 1;
6265 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6266
6267 verifiedEvent.source += 1;
6268 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6269
6270 verifiedEvent.eventTimeNanos += 1;
6271 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6272
6273 verifiedEvent.displayId += 1;
6274 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6275
6276 verifiedEvent.action += 1;
6277 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6278
6279 verifiedEvent.downTimeNanos += 1;
6280 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6281
6282 verifiedEvent.flags += 1;
6283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6284
6285 verifiedEvent.keyCode += 1;
6286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6287
6288 verifiedEvent.scanCode += 1;
6289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6290
6291 verifiedEvent.metaState += 1;
6292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6293
6294 verifiedEvent.repeatCount += 1;
6295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6296}
6297
Vishnu Nair958da932020-08-21 17:12:37 -07006298TEST_F(InputDispatcherTest, SetFocusedWindow) {
6299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6300 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006301 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006302 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006303 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006304 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6305
6306 // Top window is also focusable but is not granted focus.
6307 windowTop->setFocusable(true);
6308 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006309 mDispatcher->onWindowInfosChanged(
6310 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006311 setFocusedWindow(windowSecond);
6312
6313 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006315 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006316
6317 // Focused window should receive event.
6318 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6319 windowTop->assertNoEvents();
6320}
6321
6322TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6324 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006325 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006326 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6327
6328 window->setFocusable(true);
6329 // Release channel for window is no longer valid.
6330 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006331 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006332 setFocusedWindow(window);
6333
6334 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006335 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006336
6337 // window channel is invalid, so it should not receive any input event.
6338 window->assertNoEvents();
6339}
6340
6341TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006344 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006345 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006346 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6347
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006349 setFocusedWindow(window);
6350
6351 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006352 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006353
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006354 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006355 window->assertNoEvents();
6356}
6357
6358TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6360 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006361 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006362 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006363 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6365
6366 windowTop->setFocusable(true);
6367 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006368 mDispatcher->onWindowInfosChanged(
6369 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006370 setFocusedWindow(windowTop);
6371 windowTop->consumeFocusEvent(true);
6372
Chavi Weingarten847e8512023-03-29 00:26:09 +00006373 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006374 mDispatcher->onWindowInfosChanged(
6375 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006376 windowSecond->consumeFocusEvent(true);
6377 windowTop->consumeFocusEvent(false);
6378
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006380 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006381
6382 // Focused window should receive event.
6383 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6384}
6385
Chavi Weingarten847e8512023-03-29 00:26:09 +00006386TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6388 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006389 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006390 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006391 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006392 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6393
6394 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006395 windowSecond->setFocusable(false);
6396 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006397 mDispatcher->onWindowInfosChanged(
6398 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006399 setFocusedWindow(windowTop);
6400 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006401
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006403 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006404
6405 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006406 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006407 windowSecond->assertNoEvents();
6408}
6409
6410TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6412 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006413 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006414 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006415 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6416 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006417 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6418
6419 window->setFocusable(true);
6420 previousFocusedWindow->setFocusable(true);
6421 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006422 mDispatcher->onWindowInfosChanged(
6423 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006424 setFocusedWindow(previousFocusedWindow);
6425 previousFocusedWindow->consumeFocusEvent(true);
6426
6427 // Requesting focus on invisible window takes focus from currently focused window.
6428 setFocusedWindow(window);
6429 previousFocusedWindow->consumeFocusEvent(false);
6430
6431 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006433 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6434 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006435
6436 // Window does not get focus event or key down.
6437 window->assertNoEvents();
6438
6439 // Window becomes visible.
6440 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006441 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006442
6443 // Window receives focus event.
6444 window->consumeFocusEvent(true);
6445 // Focused window receives key down.
6446 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6447}
6448
Vishnu Nair599f1412021-06-21 10:39:58 -07006449TEST_F(InputDispatcherTest, DisplayRemoved) {
6450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6451 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006452 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006453 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6454
6455 // window is granted focus.
6456 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006457 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006458 setFocusedWindow(window);
6459 window->consumeFocusEvent(true);
6460
6461 // When a display is removed window loses focus.
6462 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6463 window->consumeFocusEvent(false);
6464}
6465
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006466/**
6467 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6468 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6469 * of the 'slipperyEnterWindow'.
6470 *
6471 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6472 * a way so that the touched location is no longer covered by the top window.
6473 *
6474 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6475 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6476 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6477 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6478 * with ACTION_DOWN).
6479 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6480 * window moved itself away from the touched location and had Flag::SLIPPERY.
6481 *
6482 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6483 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6484 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6485 *
6486 * In this test, we ensure that the event received by the bottom window has
6487 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6488 */
6489TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006490 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006491 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006492
6493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6495
6496 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006497 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006498 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006499 // Make sure this one overlaps the bottom window
6500 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6501 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6502 // one. Windows with the same owner are not considered to be occluding each other.
6503 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6504
6505 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006506 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006507 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6508
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006509 mDispatcher->onWindowInfosChanged(
6510 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006511
6512 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006513 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6514 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6515 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006516 slipperyExitWindow->consumeMotionDown();
6517 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006518 mDispatcher->onWindowInfosChanged(
6519 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006520
Prabir Pradhan678438e2023-04-13 19:32:51 +00006521 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6522 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6523 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006524
6525 slipperyExitWindow->consumeMotionCancel();
6526
6527 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6528 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6529}
6530
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006531/**
6532 * Two windows, one on the left and another on the right. The left window is slippery. The right
6533 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6534 * touch moves from the left window into the right window, the gesture should continue to go to the
6535 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6536 * reproduces a crash.
6537 */
6538TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6540
6541 sp<FakeWindowHandle> leftSlipperyWindow =
6542 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6543 leftSlipperyWindow->setSlippery(true);
6544 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6545
6546 sp<FakeWindowHandle> rightDropTouchesWindow =
6547 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6548 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6549 rightDropTouchesWindow->setDropInput(true);
6550
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006551 mDispatcher->onWindowInfosChanged(
6552 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006553
6554 // Start touch in the left window
6555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6556 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6557 .build());
6558 leftSlipperyWindow->consumeMotionDown();
6559
6560 // And move it into the right window
6561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6562 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6563 .build());
6564
6565 // Since the right window isn't eligible to receive input, touch does not slip.
6566 // The left window continues to receive the gesture.
6567 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6568 rightDropTouchesWindow->assertNoEvents();
6569}
6570
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006571/**
6572 * A single window is on screen first. Touch is injected into that window. Next, a second window
6573 * appears. Since the first window is slippery, touch will move from the first window to the second.
6574 */
6575TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6577 sp<FakeWindowHandle> originalWindow =
6578 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6579 originalWindow->setFrame(Rect(0, 0, 200, 200));
6580 originalWindow->setSlippery(true);
6581
6582 sp<FakeWindowHandle> appearingWindow =
6583 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6584 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6585
6586 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6587
6588 // Touch down on the original window
6589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6590 injectMotionEvent(*mDispatcher,
6591 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6592 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6593 .build()));
6594 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6595
6596 // Now, a new window appears. This could be, for example, a notification shade that appears
6597 // after user starts to drag down on the launcher window.
6598 mDispatcher->onWindowInfosChanged(
6599 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6601 injectMotionEvent(*mDispatcher,
6602 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6603 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6604 .build()));
6605 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6606 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6608 injectMotionEvent(*mDispatcher,
6609 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6610 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6611 .build()));
6612 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6613
6614 originalWindow->assertNoEvents();
6615 appearingWindow->assertNoEvents();
6616}
6617
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006618TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006619 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6621
6622 sp<FakeWindowHandle> leftWindow =
6623 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6624 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006625 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006626
6627 sp<FakeWindowHandle> rightSpy =
6628 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6629 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006630 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006631 rightSpy->setSpy(true);
6632 rightSpy->setTrustedOverlay(true);
6633
6634 sp<FakeWindowHandle> rightWindow =
6635 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6636 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006637 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006638
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006639 mDispatcher->onWindowInfosChanged(
6640 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006641
6642 // Touch in the left window
6643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6645 .build());
6646 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6647 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006648 ASSERT_NO_FATAL_FAILURE(
6649 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006650
6651 // Touch another finger over the right windows
6652 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6653 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6654 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6655 .build());
6656 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6657 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6658 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6659 mDispatcher->waitForIdle();
6660 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006661 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6662 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006663
6664 // Release finger over left window. The UP actions are not treated as device interaction.
6665 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6666 // is part of the UP action, we do not treat this as device interaction.
6667 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6668 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6669 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6670 .build());
6671 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6672 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6673 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6674 mDispatcher->waitForIdle();
6675 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6676
6677 // Move remaining finger
6678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6679 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6680 .build());
6681 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6682 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6683 mDispatcher->waitForIdle();
6684 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006685 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006686
6687 // Release all fingers
6688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6689 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6690 .build());
6691 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6692 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6693 mDispatcher->waitForIdle();
6694 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6695}
6696
6697TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6699
6700 sp<FakeWindowHandle> window =
6701 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6702 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006703 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006704
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006705 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006706 setFocusedWindow(window);
6707 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6708
6709 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6710 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6711 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006712 ASSERT_NO_FATAL_FAILURE(
6713 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006714
6715 // The UP actions are not treated as device interaction.
6716 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6717 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6718 mDispatcher->waitForIdle();
6719 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6720}
6721
Prabir Pradhan5893d362023-11-17 04:30:40 +00006722TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6723 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6724
6725 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6726 ADISPLAY_ID_DEFAULT);
6727 left->setFrame(Rect(0, 0, 100, 100));
6728 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6729 "Right Window", ADISPLAY_ID_DEFAULT);
6730 right->setFrame(Rect(100, 0, 200, 100));
6731 sp<FakeWindowHandle> spy =
6732 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6733 spy->setFrame(Rect(0, 0, 200, 100));
6734 spy->setTrustedOverlay(true);
6735 spy->setSpy(true);
6736
6737 mDispatcher->onWindowInfosChanged(
6738 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6739
6740 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6741 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6742 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6743 mDispatcher->notifyMotion(notifyArgs);
6744
6745 const MotionEvent& leftEnter = left->consumeMotionEvent(
6746 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6747 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6748
6749 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6750 Not(WithEventId(notifyArgs.id)),
6751 Not(WithEventId(leftEnter.getId())),
6752 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6753
6754 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6755 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6756 {PointF{150, 50}});
6757 mDispatcher->notifyMotion(notifyArgs);
6758
6759 const MotionEvent& leftExit = left->consumeMotionEvent(
6760 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6761 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6762
6763 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6764 Not(WithEventId(notifyArgs.id)),
6765 Not(WithEventId(leftExit.getId())),
6766 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6767
6768 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6769}
6770
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006771class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6772protected:
6773 std::shared_ptr<FakeApplicationHandle> mApp;
6774 sp<FakeWindowHandle> mWindow;
6775
6776 virtual void SetUp() override {
6777 InputDispatcherTest::SetUp();
6778
6779 mApp = std::make_shared<FakeApplicationHandle>();
6780
6781 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6782 mWindow->setFrame(Rect(0, 0, 100, 100));
6783
6784 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6785 setFocusedWindow(mWindow);
6786 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6787 }
6788
6789 void setFallback(int32_t keycode) {
6790 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6791 return KeyEventBuilder(event).keyCode(keycode).build();
6792 });
6793 }
6794
6795 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006796 const KeyEvent& event = mWindow->consumeKey(handled);
6797 ASSERT_THAT(event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006798 }
6799};
6800
6801TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6802 mDispatcher->notifyKey(
6803 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6804 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6805 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6806}
6807
6808TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6809 mDispatcher->notifyKey(
6810 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6811 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6812 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6813}
6814
6815TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6816 mDispatcher->notifyKey(
6817 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6818
6819 // Do not handle this key event.
6820 consumeKey(/*handled=*/false,
6821 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6822 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6823
6824 // Since the policy did not request any fallback to be generated, ensure there are no events.
6825 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6826}
6827
6828TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6829 setFallback(AKEYCODE_B);
6830 mDispatcher->notifyKey(
6831 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6832
6833 // Do not handle this key event.
6834 consumeKey(/*handled=*/false,
6835 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6836
6837 // Since the key was not handled, ensure the fallback event was dispatched instead.
6838 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6839 consumeKey(/*handled=*/true,
6840 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6841 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6842
6843 // Release the original key, and ensure the fallback key is also released.
6844 mDispatcher->notifyKey(
6845 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6846 consumeKey(/*handled=*/false,
6847 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6848 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6849 consumeKey(/*handled=*/true,
6850 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6851 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6852
6853 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6854 mWindow->assertNoEvents();
6855}
6856
6857TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6858 setFallback(AKEYCODE_B);
6859 mDispatcher->notifyKey(
6860 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6861
6862 // Do not handle this key event, but handle the fallback.
6863 consumeKey(/*handled=*/false,
6864 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6865 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6866 consumeKey(/*handled=*/true,
6867 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6868 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6869
6870 // Release the original key, and ensure the fallback key is also released.
6871 mDispatcher->notifyKey(
6872 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6873 // But this time, the app handles the original key.
6874 consumeKey(/*handled=*/true,
6875 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6876 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6877 // Ensure the fallback key is canceled.
6878 consumeKey(/*handled=*/true,
6879 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6880 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6881
6882 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6883 mWindow->assertNoEvents();
6884}
6885
6886TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6887 setFallback(AKEYCODE_B);
6888 mDispatcher->notifyKey(
6889 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6890
6891 // Do not handle this key event.
6892 consumeKey(/*handled=*/false,
6893 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6894 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6895 // App does not handle the fallback either, so ensure another fallback is not generated.
6896 setFallback(AKEYCODE_C);
6897 consumeKey(/*handled=*/false,
6898 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6899 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6900
6901 // Release the original key, and ensure the fallback key is also released.
6902 setFallback(AKEYCODE_B);
6903 mDispatcher->notifyKey(
6904 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6905 consumeKey(/*handled=*/false,
6906 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6907 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6908 consumeKey(/*handled=*/false,
6909 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6910 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6911
6912 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6913 mWindow->assertNoEvents();
6914}
6915
6916TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6917 setFallback(AKEYCODE_B);
6918 mDispatcher->notifyKey(
6919 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6920
6921 // Do not handle this key event, so fallback is generated.
6922 consumeKey(/*handled=*/false,
6923 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6924 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6925 consumeKey(/*handled=*/true,
6926 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6927 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6928
6929 // Release the original key, but assume the policy is misbehaving and it
6930 // generates an inconsistent fallback to the one from the DOWN event.
6931 setFallback(AKEYCODE_C);
6932 mDispatcher->notifyKey(
6933 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6934 consumeKey(/*handled=*/false,
6935 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6936 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6937 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6938 consumeKey(/*handled=*/true,
6939 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6940 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6941
6942 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6943 mWindow->assertNoEvents();
6944}
6945
6946TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6947 setFallback(AKEYCODE_B);
6948 mDispatcher->notifyKey(
6949 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6950
6951 // Do not handle this key event, so fallback is generated.
6952 consumeKey(/*handled=*/false,
6953 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6954 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6955 consumeKey(/*handled=*/true,
6956 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6957 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6958
6959 // The original key is canceled.
6960 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6961 .keyCode(AKEYCODE_A)
6962 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6963 .build());
6964 consumeKey(/*handled=*/false,
6965 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6966 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6967 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6968 // Ensure the fallback key is also canceled due to the original key being canceled.
6969 consumeKey(/*handled=*/true,
6970 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6971 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6972
6973 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6974 mWindow->assertNoEvents();
6975}
6976
Garfield Tan1c7bc862020-01-28 13:24:04 -08006977class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6978protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006979 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6980 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006981
Chris Yea209fde2020-07-22 13:54:51 -07006982 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006983 sp<FakeWindowHandle> mWindow;
6984
6985 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00006986 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00006987 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00006988 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09006989 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006990 ASSERT_EQ(OK, mDispatcher->start());
6991
6992 setUpWindow();
6993 }
6994
6995 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07006996 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006997 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08006998
Vishnu Nair47074b82020-08-14 11:54:47 -07006999 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007000 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007001 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007002 mWindow->consumeFocusEvent(true);
7003 }
7004
Chris Ye2ad95392020-09-01 13:44:44 -07007005 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007006 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007007 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007008 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007009 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007010
7011 // Window should receive key down event.
7012 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7013 }
7014
7015 void expectKeyRepeatOnce(int32_t repeatCount) {
7016 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007017 mWindow->consumeKeyEvent(
7018 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007019 }
7020
Chris Ye2ad95392020-09-01 13:44:44 -07007021 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007022 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007023 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007024 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007025 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007026
7027 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007028 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007029 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007030 }
7031};
7032
7033TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007034 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007035 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7036 expectKeyRepeatOnce(repeatCount);
7037 }
7038}
7039
7040TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007041 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007042 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7043 expectKeyRepeatOnce(repeatCount);
7044 }
Harry Cutts33476232023-01-30 19:57:29 +00007045 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007046 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007047 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7048 expectKeyRepeatOnce(repeatCount);
7049 }
7050}
7051
7052TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007053 sendAndConsumeKeyDown(/*deviceId=*/1);
7054 expectKeyRepeatOnce(/*repeatCount=*/1);
7055 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007056 mWindow->assertNoEvents();
7057}
7058
7059TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007060 sendAndConsumeKeyDown(/*deviceId=*/1);
7061 expectKeyRepeatOnce(/*repeatCount=*/1);
7062 sendAndConsumeKeyDown(/*deviceId=*/2);
7063 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007064 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007065 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007066 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007067 expectKeyRepeatOnce(/*repeatCount=*/2);
7068 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007069 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007070 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007071 mWindow->assertNoEvents();
7072}
7073
7074TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007075 sendAndConsumeKeyDown(/*deviceId=*/1);
7076 expectKeyRepeatOnce(/*repeatCount=*/1);
7077 sendAndConsumeKeyDown(/*deviceId=*/2);
7078 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007079 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007080 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007081 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007082 mWindow->assertNoEvents();
7083}
7084
liushenxiang42232912021-05-21 20:24:09 +08007085TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7086 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007087 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007088 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007089 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7090 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7091 mWindow->assertNoEvents();
7092}
7093
Garfield Tan1c7bc862020-01-28 13:24:04 -08007094TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007095 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007096 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007097 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007098 const KeyEvent& repeatEvent = mWindow->consumeKey();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007099 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007100 IdGenerator::getSource(repeatEvent.getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007101 }
7102}
7103
7104TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007105 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007106 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007107
7108 std::unordered_set<int32_t> idSet;
7109 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007110 const KeyEvent& repeatEvent = mWindow->consumeKey();
7111 int32_t id = repeatEvent.getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007112 EXPECT_EQ(idSet.end(), idSet.find(id));
7113 idSet.insert(id);
7114 }
7115}
7116
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007117/* Test InputDispatcher for MultiDisplay */
7118class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7119public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007120 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007121 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007122
Chris Yea209fde2020-07-22 13:54:51 -07007123 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007124 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007125 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007126
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007127 // Set focus window for primary display, but focused display would be second one.
7128 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007129 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007130 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7131
Vishnu Nair958da932020-08-21 17:12:37 -07007132 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007133 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007134
Chris Yea209fde2020-07-22 13:54:51 -07007135 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007136 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007137 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007138 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007139 // Set focus display to second one.
7140 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7141 // Set focus window for second display.
7142 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007143 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007144 mDispatcher->onWindowInfosChanged(
7145 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007146 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007147 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007148 }
7149
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007150 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007151 InputDispatcherTest::TearDown();
7152
Chris Yea209fde2020-07-22 13:54:51 -07007153 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007154 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007155 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007156 windowInSecondary.clear();
7157 }
7158
7159protected:
Chris Yea209fde2020-07-22 13:54:51 -07007160 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007161 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007162 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007163 sp<FakeWindowHandle> windowInSecondary;
7164};
7165
7166TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7167 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007169 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007171 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007172 windowInSecondary->assertNoEvents();
7173
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007174 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007176 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007178 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007179 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007180}
7181
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007182TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007183 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007185 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007186 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007187 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007188 windowInSecondary->assertNoEvents();
7189
7190 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007192 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007193 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007194 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007195
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007196 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007197 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007198
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007199 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007200 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007201
7202 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007203 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007204 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007205 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007206 windowInSecondary->assertNoEvents();
7207}
7208
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007209// Test per-display input monitors for motion event.
7210TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007211 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007212 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007213 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007214 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007215
7216 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007218 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007220 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007221 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007222 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007223 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007224
7225 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007227 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007229 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007230 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007231 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007232 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007233
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007234 // Lift up the touch from the second display
7235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7238 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7239 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7240
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007241 // Test inject a non-pointer motion event.
7242 // If specific a display, it will dispatch to the focused window of particular display,
7243 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007245 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007247 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007248 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007249 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007250 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007251}
7252
7253// Test per-display input monitors for key event.
7254TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007255 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007256 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007257 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007258 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007259 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007260
7261 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007263 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007264 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007265 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007266 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007267 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007268}
7269
Vishnu Nair958da932020-08-21 17:12:37 -07007270TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7271 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007272 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007273 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007274 mDispatcher->onWindowInfosChanged(
7275 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7276 *windowInSecondary->getInfo()},
7277 {},
7278 0,
7279 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007280 setFocusedWindow(secondWindowInPrimary);
7281 windowInPrimary->consumeFocusEvent(false);
7282 secondWindowInPrimary->consumeFocusEvent(true);
7283
7284 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7286 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007287 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007288 windowInPrimary->assertNoEvents();
7289 windowInSecondary->assertNoEvents();
7290 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7291}
7292
Arthur Hungdfd528e2021-12-08 13:23:04 +00007293TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7294 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007295 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007296 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007297 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007298
7299 // Test touch down on primary display.
7300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007301 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7303 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7304 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7305
7306 // Test touch down on second display.
7307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007308 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007309 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7310 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7311 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7312
7313 // Trigger cancel touch.
7314 mDispatcher->cancelCurrentTouch();
7315 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7316 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7317 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7318 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7319
7320 // Test inject a move motion event, no window/monitor should receive the event.
7321 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007322 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007323 ADISPLAY_ID_DEFAULT, {110, 200}))
7324 << "Inject motion event should return InputEventInjectionResult::FAILED";
7325 windowInPrimary->assertNoEvents();
7326 monitorInPrimary.assertNoEvents();
7327
7328 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007329 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007330 SECOND_DISPLAY_ID, {110, 200}))
7331 << "Inject motion event should return InputEventInjectionResult::FAILED";
7332 windowInSecondary->assertNoEvents();
7333 monitorInSecondary.assertNoEvents();
7334}
7335
Jackal Guof9696682018-10-05 12:23:23 +08007336class InputFilterTest : public InputDispatcherTest {
7337protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007338 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7339 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007340 NotifyMotionArgs motionArgs;
7341
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007342 motionArgs =
7343 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007344 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007345 motionArgs =
7346 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007347 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007348 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007349 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007350 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007351 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007352 } else {
7353 mFakePolicy->assertFilterInputEventWasNotCalled();
7354 }
7355 }
7356
7357 void testNotifyKey(bool expectToBeFiltered) {
7358 NotifyKeyArgs keyArgs;
7359
7360 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007361 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007362 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007363 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007364 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007365
7366 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007367 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007368 } else {
7369 mFakePolicy->assertFilterInputEventWasNotCalled();
7370 }
7371 }
7372};
7373
7374// Test InputFilter for MotionEvent
7375TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7376 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007377 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7378 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007379
7380 // Enable InputFilter
7381 mDispatcher->setInputFilterEnabled(true);
7382 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007383 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7384 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007385
7386 // Disable InputFilter
7387 mDispatcher->setInputFilterEnabled(false);
7388 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007389 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7390 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007391}
7392
7393// Test InputFilter for KeyEvent
7394TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7395 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007396 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007397
7398 // Enable InputFilter
7399 mDispatcher->setInputFilterEnabled(true);
7400 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007401 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007402
7403 // Disable InputFilter
7404 mDispatcher->setInputFilterEnabled(false);
7405 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007406 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007407}
7408
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007409// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7410// logical display coordinate space.
7411TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7412 ui::Transform firstDisplayTransform;
7413 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7414 ui::Transform secondDisplayTransform;
7415 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7416
7417 std::vector<gui::DisplayInfo> displayInfos(2);
7418 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7419 displayInfos[0].transform = firstDisplayTransform;
7420 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7421 displayInfos[1].transform = secondDisplayTransform;
7422
Patrick Williamsd828f302023-04-28 17:52:08 -05007423 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007424
7425 // Enable InputFilter
7426 mDispatcher->setInputFilterEnabled(true);
7427
7428 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007429 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7430 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007431}
7432
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007433class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7434protected:
7435 virtual void SetUp() override {
7436 InputDispatcherTest::SetUp();
7437
7438 /**
7439 * We don't need to enable input filter to test the injected event policy, but we enabled it
7440 * here to make the tests more realistic, since this policy only matters when inputfilter is
7441 * on.
7442 */
7443 mDispatcher->setInputFilterEnabled(true);
7444
7445 std::shared_ptr<InputApplicationHandle> application =
7446 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007447 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7448 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007449
7450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7451 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007452 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007453 setFocusedWindow(mWindow);
7454 mWindow->consumeFocusEvent(true);
7455 }
7456
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007457 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7458 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007459 KeyEvent event;
7460
7461 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7462 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7463 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007464 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007465 const int32_t additionalPolicyFlags =
7466 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007468 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007469 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007470 policyFlags | additionalPolicyFlags));
7471
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007472 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007473 }
7474
7475 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7476 int32_t flags) {
7477 MotionEvent event;
7478 PointerProperties pointerProperties[1];
7479 PointerCoords pointerCoords[1];
7480 pointerProperties[0].clear();
7481 pointerProperties[0].id = 0;
7482 pointerCoords[0].clear();
7483 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7484 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7485
7486 ui::Transform identityTransform;
7487 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7488 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7489 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7490 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7491 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007492 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007493 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007494 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007495
7496 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007498 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007499 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007500 policyFlags | additionalPolicyFlags));
7501
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007502 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007503 }
7504
7505private:
7506 sp<FakeWindowHandle> mWindow;
7507};
7508
7509TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007510 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7511 // filter. Without it, the event will no different from a regularly injected event, and the
7512 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007513 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7514 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007515}
7516
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007517TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007518 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007519 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007520 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7521}
7522
7523TEST_F(InputFilterInjectionPolicyTest,
7524 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7525 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007526 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007527 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007528}
7529
7530TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007531 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7532 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007533}
7534
chaviwfd6d3512019-03-25 13:23:49 -07007535class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007536 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007537 InputDispatcherTest::SetUp();
7538
Chris Yea209fde2020-07-22 13:54:51 -07007539 std::shared_ptr<FakeApplicationHandle> application =
7540 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007541 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007542 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007543 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007544
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007545 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007546 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007547 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007548
7549 // Set focused application.
7550 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007551 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007552
7553 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007554 mDispatcher->onWindowInfosChanged(
7555 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007556 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007557 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007558 }
7559
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007560 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007561 InputDispatcherTest::TearDown();
7562
7563 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007564 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007565 }
7566
7567protected:
7568 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007569 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007570 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007571};
7572
7573// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7574// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7575// the onPointerDownOutsideFocus callback.
7576TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007578 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007579 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007581 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007582
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007583 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007584 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7585}
7586
7587// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7588// DOWN on the window that doesn't have focus. Ensure no window received the
7589// onPointerDownOutsideFocus callback.
7590TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7593 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007594 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007595 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007596
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007597 ASSERT_TRUE(mDispatcher->waitForIdle());
7598 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007599}
7600
7601// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7602// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7603TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007605 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007606 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007607 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007608
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007609 ASSERT_TRUE(mDispatcher->waitForIdle());
7610 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007611}
7612
7613// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7614// DOWN on the window that already has focus. Ensure no window received the
7615// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007616TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007618 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007619 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007621 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007622
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007623 ASSERT_TRUE(mDispatcher->waitForIdle());
7624 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007625}
7626
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007627// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7628// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7629TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7630 const MotionEvent event =
7631 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7632 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007633 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007634 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7635 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7638 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7639
7640 ASSERT_TRUE(mDispatcher->waitForIdle());
7641 mFakePolicy->assertOnPointerDownWasNotCalled();
7642 // Ensure that the unfocused window did not receive any FOCUS events.
7643 mUnfocusedWindow->assertNoEvents();
7644}
7645
chaviwaf87b3e2019-10-01 16:59:28 -07007646// These tests ensures we can send touch events to a single client when there are multiple input
7647// windows that point to the same client token.
7648class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7649 virtual void SetUp() override {
7650 InputDispatcherTest::SetUp();
7651
Chris Yea209fde2020-07-22 13:54:51 -07007652 std::shared_ptr<FakeApplicationHandle> application =
7653 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007654 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7655 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007656 mWindow1->setFrame(Rect(0, 0, 100, 100));
7657
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00007658 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
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 Vishniakou99e407b2023-12-26 18:09:32 -08008812/**
8813 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
8814 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
8815 * dispatcher doesn't prune pointer events incorrectly.
8816 *
8817 * This test reproduces a crash in InputDispatcher.
8818 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
8819 *
8820 * Keep the currently focused application (mApplication), and have no focused window.
8821 * We set up two additional windows:
8822 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
8823 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
8824 * window. This window is not focusable, but is touchable.
8825 *
8826 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
8827 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
8828 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
8829 *
8830 * Now, we touch "Another window". This window is owned by a different application than
8831 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
8832 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
8833 * dropping the events from its queue. Ensure that no crash occurs.
8834 *
8835 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
8836 * This does not affect the test running time.
8837 */
8838TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
8839 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
8840 std::make_shared<FakeApplicationHandle>();
8841 systemUiApplication->setDispatchingTimeout(3000ms);
8842 mFakePolicy->setStaleEventTimeout(3000ms);
8843 sp<FakeWindowHandle> navigationBar =
8844 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
8845 ADISPLAY_ID_DEFAULT);
8846 navigationBar->setFocusable(false);
8847 navigationBar->setWatchOutsideTouch(true);
8848 navigationBar->setFrame(Rect(0, 0, 100, 100));
8849
8850 mApplication->setDispatchingTimeout(3000ms);
8851 // 'mApplication' is already focused, but we call it again here to make it explicit.
8852 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8853
8854 std::shared_ptr<FakeApplicationHandle> anotherApplication =
8855 std::make_shared<FakeApplicationHandle>();
8856 sp<FakeWindowHandle> appWindow =
8857 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
8858 ADISPLAY_ID_DEFAULT);
8859 appWindow->setFocusable(false);
8860 appWindow->setFrame(Rect(100, 100, 200, 200));
8861
8862 mDispatcher->onWindowInfosChanged(
8863 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
8864 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
8865 mFocusedWindow->consumeFocusEvent(false);
8866
8867 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
8868 // in response.
8869 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8870 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8871 .build());
8872 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8873
8874 // Key will not be sent anywhere because we have no focused window. It will remain pending.
8875 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
8876 InputEventInjectionResult result =
8877 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8878 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8879 /*allowKeyRepeat=*/false);
8880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8881
8882 // Finish the gesture - lift up finger and inject ACTION_UP key event
8883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8884 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8885 .build());
8886 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8887 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8888 /*allowKeyRepeat=*/false);
8889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8890 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
8891 // getting any events yet.
8892 navigationBar->assertNoEvents();
8893
8894 // Now touch "Another window". This touch is going to a different application than the one we
8895 // are waiting for (which is 'mApplication').
8896 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
8897 // trying to be injected) and to continue processing the rest of the events in the original
8898 // order.
8899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8900 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8901 .build());
8902 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
8903 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
8904 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8905
8906 appWindow->assertNoEvents();
8907 navigationBar->assertNoEvents();
8908}
8909
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008910// These tests ensure we cannot send touch events to a window that's positioned behind a window
8911// that has feature NO_INPUT_CHANNEL.
8912// Layout:
8913// Top (closest to user)
8914// mNoInputWindow (above all windows)
8915// mBottomWindow
8916// Bottom (furthest from user)
8917class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8918 virtual void SetUp() override {
8919 InputDispatcherTest::SetUp();
8920
8921 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008922 mNoInputWindow =
8923 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8924 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008925 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008926 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008927 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8928 // It's perfectly valid for this window to not have an associated input channel
8929
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008930 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8931 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008932 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8933
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008934 mDispatcher->onWindowInfosChanged(
8935 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008936 }
8937
8938protected:
8939 std::shared_ptr<FakeApplicationHandle> mApplication;
8940 sp<FakeWindowHandle> mNoInputWindow;
8941 sp<FakeWindowHandle> mBottomWindow;
8942};
8943
8944TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8945 PointF touchedPoint = {10, 10};
8946
Prabir Pradhan678438e2023-04-13 19:32:51 +00008947 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8948 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8949 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008950
8951 mNoInputWindow->assertNoEvents();
8952 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8953 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8954 // and therefore should prevent mBottomWindow from receiving touches
8955 mBottomWindow->assertNoEvents();
8956}
8957
8958/**
8959 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8960 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8961 */
8962TEST_F(InputDispatcherMultiWindowOcclusionTests,
8963 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008964 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8965 "Window with input channel and NO_INPUT_CHANNEL",
8966 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008967
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008968 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008969 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008970 mDispatcher->onWindowInfosChanged(
8971 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008972
8973 PointF touchedPoint = {10, 10};
8974
Prabir Pradhan678438e2023-04-13 19:32:51 +00008975 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8976 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8977 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008978
8979 mNoInputWindow->assertNoEvents();
8980 mBottomWindow->assertNoEvents();
8981}
8982
Vishnu Nair958da932020-08-21 17:12:37 -07008983class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
8984protected:
8985 std::shared_ptr<FakeApplicationHandle> mApp;
8986 sp<FakeWindowHandle> mWindow;
8987 sp<FakeWindowHandle> mMirror;
8988
8989 virtual void SetUp() override {
8990 InputDispatcherTest::SetUp();
8991 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008992 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008993 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008994 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
8995 mWindow->setFocusable(true);
8996 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008997 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008998 }
8999};
9000
9001TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9002 // Request focus on a mirrored window
9003 setFocusedWindow(mMirror);
9004
9005 // window gets focused
9006 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009008 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009009 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9010}
9011
9012// A focused & mirrored window remains focused only if the window and its mirror are both
9013// focusable.
9014TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9015 setFocusedWindow(mMirror);
9016
9017 // window gets focused
9018 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009020 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009021 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009023 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009024 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9025
9026 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009027 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009028
9029 // window loses focus since one of the windows associated with the token in not focusable
9030 mWindow->consumeFocusEvent(false);
9031
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009032 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009033 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009034 mWindow->assertNoEvents();
9035}
9036
9037// A focused & mirrored window remains focused until the window and its mirror both become
9038// invisible.
9039TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9040 setFocusedWindow(mMirror);
9041
9042 // window gets focused
9043 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009045 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009046 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009048 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009049 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9050
9051 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009052 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009053
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009055 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009056 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009058 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009059 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9060
9061 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009062 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009063
9064 // window loses focus only after all windows associated with the token become invisible.
9065 mWindow->consumeFocusEvent(false);
9066
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009067 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009068 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009069 mWindow->assertNoEvents();
9070}
9071
9072// A focused & mirrored window remains focused until both windows are removed.
9073TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9074 setFocusedWindow(mMirror);
9075
9076 // window gets focused
9077 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009079 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009080 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009082 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009083 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9084
9085 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009086 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009087
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009089 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009090 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009092 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009093 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9094
9095 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009096 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009097 mWindow->consumeFocusEvent(false);
9098
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009099 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009100 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009101 mWindow->assertNoEvents();
9102}
9103
9104// Focus request can be pending until one window becomes visible.
9105TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9106 // Request focus on an invisible mirror.
9107 mWindow->setVisible(false);
9108 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009109 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009110 setFocusedWindow(mMirror);
9111
9112 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009114 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9115 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009116
9117 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009118 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009119
9120 // window gets focused
9121 mWindow->consumeFocusEvent(true);
9122 // window gets the pending key event
9123 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9124}
Prabir Pradhan99987712020-11-10 18:43:05 -08009125
9126class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9127protected:
9128 std::shared_ptr<FakeApplicationHandle> mApp;
9129 sp<FakeWindowHandle> mWindow;
9130 sp<FakeWindowHandle> mSecondWindow;
9131
9132 void SetUp() override {
9133 InputDispatcherTest::SetUp();
9134 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009135 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009136 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009137 mSecondWindow =
9138 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009139 mSecondWindow->setFocusable(true);
9140
9141 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009142 mDispatcher->onWindowInfosChanged(
9143 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009144
9145 setFocusedWindow(mWindow);
9146 mWindow->consumeFocusEvent(true);
9147 }
9148
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009149 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009150 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009151 }
9152
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009153 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9154 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009155 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009156 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9157 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009158 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009159 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009160 }
9161};
9162
9163TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9164 // Ensure that capture cannot be obtained for unfocused windows.
9165 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9166 mFakePolicy->assertSetPointerCaptureNotCalled();
9167 mSecondWindow->assertNoEvents();
9168
9169 // Ensure that capture can be enabled from the focus window.
9170 requestAndVerifyPointerCapture(mWindow, true);
9171
9172 // Ensure that capture cannot be disabled from a window that does not have capture.
9173 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9174 mFakePolicy->assertSetPointerCaptureNotCalled();
9175
9176 // Ensure that capture can be disabled from the window with capture.
9177 requestAndVerifyPointerCapture(mWindow, false);
9178}
9179
9180TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009181 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009182
9183 setFocusedWindow(mSecondWindow);
9184
9185 // Ensure that the capture disabled event was sent first.
9186 mWindow->consumeCaptureEvent(false);
9187 mWindow->consumeFocusEvent(false);
9188 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009189 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009190
9191 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009192 notifyPointerCaptureChanged({});
9193 notifyPointerCaptureChanged(request);
9194 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009195 mWindow->assertNoEvents();
9196 mSecondWindow->assertNoEvents();
9197 mFakePolicy->assertSetPointerCaptureNotCalled();
9198}
9199
9200TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009201 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009202
9203 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009204 notifyPointerCaptureChanged({});
9205 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009206
9207 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009208 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009209 mWindow->consumeCaptureEvent(false);
9210 mWindow->assertNoEvents();
9211}
9212
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009213TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9214 requestAndVerifyPointerCapture(mWindow, true);
9215
9216 // The first window loses focus.
9217 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009218 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009219 mWindow->consumeCaptureEvent(false);
9220
9221 // Request Pointer Capture from the second window before the notification from InputReader
9222 // arrives.
9223 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009224 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009225
9226 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009227 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009228
9229 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009230 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009231
9232 mSecondWindow->consumeFocusEvent(true);
9233 mSecondWindow->consumeCaptureEvent(true);
9234}
9235
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009236TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9237 // App repeatedly enables and disables capture.
9238 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9239 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9240 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9241 mFakePolicy->assertSetPointerCaptureCalled(false);
9242 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9243 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9244
9245 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9246 // first request is now stale, this should do nothing.
9247 notifyPointerCaptureChanged(firstRequest);
9248 mWindow->assertNoEvents();
9249
9250 // InputReader notifies that the second request was enabled.
9251 notifyPointerCaptureChanged(secondRequest);
9252 mWindow->consumeCaptureEvent(true);
9253}
9254
Prabir Pradhan7092e262022-05-03 16:51:09 +00009255TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9256 requestAndVerifyPointerCapture(mWindow, true);
9257
9258 // App toggles pointer capture off and on.
9259 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9260 mFakePolicy->assertSetPointerCaptureCalled(false);
9261
9262 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9263 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9264
9265 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9266 // preceding "disable" request.
9267 notifyPointerCaptureChanged(enableRequest);
9268
9269 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9270 // any notifications.
9271 mWindow->assertNoEvents();
9272}
9273
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009274/**
9275 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9276 * mouse movements don't affect the previous mouse hovering state.
9277 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9278 * HOVER_MOVE events).
9279 */
9280TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9281 // Mouse hover on the window
9282 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9283 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9284 .build());
9285 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9286 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9287 .build());
9288
9289 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9290 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9291
9292 // Start pointer capture
9293 requestAndVerifyPointerCapture(mWindow, true);
9294
9295 // Send some relative mouse movements and receive them in the window.
9296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9297 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9298 .build());
9299 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9300 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9301
9302 // Stop pointer capture
9303 requestAndVerifyPointerCapture(mWindow, false);
9304
9305 // Continue hovering on the window
9306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9307 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9308 .build());
9309 mWindow->consumeMotionEvent(
9310 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9311
9312 mWindow->assertNoEvents();
9313}
9314
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009315class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9316protected:
9317 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009318
9319 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9320 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9321
9322 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9323 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9324
9325 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9326 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9327 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9328 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9329 MAXIMUM_OBSCURING_OPACITY);
9330
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009331 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9332 static constexpr gui::Uid APP_B_UID{10002};
9333 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009334
9335 sp<FakeWindowHandle> mTouchWindow;
9336
9337 virtual void SetUp() override {
9338 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009339 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009340 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9341 }
9342
9343 virtual void TearDown() override {
9344 InputDispatcherTest::TearDown();
9345 mTouchWindow.clear();
9346 }
9347
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009348 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009349 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009350 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009351 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009352 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009353 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009354 return window;
9355 }
9356
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009357 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009358 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9359 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009360 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009361 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009362 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009363 return window;
9364 }
9365
9366 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009367 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9368 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9369 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009370 }
9371};
9372
9373TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009374 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009375 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009376 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009377
9378 touch();
9379
9380 mTouchWindow->assertNoEvents();
9381}
9382
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009383TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009384 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9385 const sp<FakeWindowHandle>& w =
9386 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009387 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009388
9389 touch();
9390
9391 mTouchWindow->assertNoEvents();
9392}
9393
9394TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009395 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9396 const sp<FakeWindowHandle>& w =
9397 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009398 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009399
9400 touch();
9401
9402 w->assertNoEvents();
9403}
9404
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009405TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009406 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009407 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009408
9409 touch();
9410
9411 mTouchWindow->consumeAnyMotionDown();
9412}
9413
9414TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009415 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009416 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009417 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009418 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009419
9420 touch({PointF{100, 100}});
9421
9422 mTouchWindow->consumeAnyMotionDown();
9423}
9424
9425TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009426 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009427 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009428 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009429
9430 touch();
9431
9432 mTouchWindow->consumeAnyMotionDown();
9433}
9434
9435TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9436 const sp<FakeWindowHandle>& w =
9437 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009438 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009439
9440 touch();
9441
9442 mTouchWindow->consumeAnyMotionDown();
9443}
9444
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009445TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9446 const sp<FakeWindowHandle>& w =
9447 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009448 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009449
9450 touch();
9451
9452 w->assertNoEvents();
9453}
9454
9455/**
9456 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9457 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9458 * window, the occluding window will still receive ACTION_OUTSIDE event.
9459 */
9460TEST_F(InputDispatcherUntrustedTouchesTest,
9461 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9462 const sp<FakeWindowHandle>& w =
9463 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009464 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009465 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009466
9467 touch();
9468
9469 w->consumeMotionOutside();
9470}
9471
9472TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9473 const sp<FakeWindowHandle>& w =
9474 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009475 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009476 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009477
9478 touch();
9479
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009480 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009481}
9482
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009483TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009484 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009485 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9486 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009487 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009488
9489 touch();
9490
9491 mTouchWindow->consumeAnyMotionDown();
9492}
9493
9494TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9495 const sp<FakeWindowHandle>& w =
9496 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9497 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009498 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009499
9500 touch();
9501
9502 mTouchWindow->consumeAnyMotionDown();
9503}
9504
9505TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009506 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009507 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9508 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009509 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009510
9511 touch();
9512
9513 mTouchWindow->assertNoEvents();
9514}
9515
9516TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9517 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9518 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009519 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9520 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009521 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009522 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9523 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009524 mDispatcher->onWindowInfosChanged(
9525 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009526
9527 touch();
9528
9529 mTouchWindow->assertNoEvents();
9530}
9531
9532TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9533 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9534 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009535 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9536 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009537 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009538 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9539 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009540 mDispatcher->onWindowInfosChanged(
9541 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009542
9543 touch();
9544
9545 mTouchWindow->consumeAnyMotionDown();
9546}
9547
9548TEST_F(InputDispatcherUntrustedTouchesTest,
9549 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9550 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009551 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9552 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009553 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009554 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9555 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009556 mDispatcher->onWindowInfosChanged(
9557 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009558
9559 touch();
9560
9561 mTouchWindow->consumeAnyMotionDown();
9562}
9563
9564TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9565 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009566 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9567 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009568 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009569 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9570 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009571 mDispatcher->onWindowInfosChanged(
9572 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009573
9574 touch();
9575
9576 mTouchWindow->assertNoEvents();
9577}
9578
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009579TEST_F(InputDispatcherUntrustedTouchesTest,
9580 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9581 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009582 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9583 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009584 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009585 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9586 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009587 mDispatcher->onWindowInfosChanged(
9588 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009589
9590 touch();
9591
9592 mTouchWindow->assertNoEvents();
9593}
9594
9595TEST_F(InputDispatcherUntrustedTouchesTest,
9596 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9597 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009598 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9599 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009600 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009601 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9602 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009603 mDispatcher->onWindowInfosChanged(
9604 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009605
9606 touch();
9607
9608 mTouchWindow->consumeAnyMotionDown();
9609}
9610
9611TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9612 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009613 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9614 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009615 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009616
9617 touch();
9618
9619 mTouchWindow->consumeAnyMotionDown();
9620}
9621
9622TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9623 const sp<FakeWindowHandle>& w =
9624 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009625 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009626
9627 touch();
9628
9629 mTouchWindow->consumeAnyMotionDown();
9630}
9631
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009632TEST_F(InputDispatcherUntrustedTouchesTest,
9633 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9634 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9635 const sp<FakeWindowHandle>& w =
9636 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009637 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009638
9639 touch();
9640
9641 mTouchWindow->assertNoEvents();
9642}
9643
9644TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9645 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9646 const sp<FakeWindowHandle>& w =
9647 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009648 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009649
9650 touch();
9651
9652 mTouchWindow->consumeAnyMotionDown();
9653}
9654
9655TEST_F(InputDispatcherUntrustedTouchesTest,
9656 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9657 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9658 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009659 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9660 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009661 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009662
9663 touch();
9664
9665 mTouchWindow->consumeAnyMotionDown();
9666}
9667
9668TEST_F(InputDispatcherUntrustedTouchesTest,
9669 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9670 const sp<FakeWindowHandle>& w1 =
9671 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9672 OPACITY_BELOW_THRESHOLD);
9673 const sp<FakeWindowHandle>& w2 =
9674 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9675 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009676 mDispatcher->onWindowInfosChanged(
9677 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009678
9679 touch();
9680
9681 mTouchWindow->assertNoEvents();
9682}
9683
9684/**
9685 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9686 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9687 * (which alone would result in allowing touches) does not affect the blocking behavior.
9688 */
9689TEST_F(InputDispatcherUntrustedTouchesTest,
9690 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9691 const sp<FakeWindowHandle>& wB =
9692 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9693 OPACITY_BELOW_THRESHOLD);
9694 const sp<FakeWindowHandle>& wC =
9695 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9696 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009697 mDispatcher->onWindowInfosChanged(
9698 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009699
9700 touch();
9701
9702 mTouchWindow->assertNoEvents();
9703}
9704
9705/**
9706 * This test is testing that a window from a different UID but with same application token doesn't
9707 * block the touch. Apps can share the application token for close UI collaboration for example.
9708 */
9709TEST_F(InputDispatcherUntrustedTouchesTest,
9710 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9711 const sp<FakeWindowHandle>& w =
9712 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9713 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009714 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009715
9716 touch();
9717
9718 mTouchWindow->consumeAnyMotionDown();
9719}
9720
arthurhungb89ccb02020-12-30 16:19:01 +08009721class InputDispatcherDragTests : public InputDispatcherTest {
9722protected:
9723 std::shared_ptr<FakeApplicationHandle> mApp;
9724 sp<FakeWindowHandle> mWindow;
9725 sp<FakeWindowHandle> mSecondWindow;
9726 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009727 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009728 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9729 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009730
9731 void SetUp() override {
9732 InputDispatcherTest::SetUp();
9733 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009734 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009735 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009736
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009737 mSecondWindow =
9738 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009739 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009740
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009741 mSpyWindow =
9742 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009743 mSpyWindow->setSpy(true);
9744 mSpyWindow->setTrustedOverlay(true);
9745 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9746
arthurhungb89ccb02020-12-30 16:19:01 +08009747 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009748 mDispatcher->onWindowInfosChanged(
9749 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9750 {},
9751 0,
9752 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009753 }
9754
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009755 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9756 switch (fromSource) {
9757 case AINPUT_SOURCE_TOUCHSCREEN:
9758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009759 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009760 ADISPLAY_ID_DEFAULT, {50, 50}))
9761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9762 break;
9763 case AINPUT_SOURCE_STYLUS:
9764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009765 injectMotionEvent(*mDispatcher,
9766 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9767 AINPUT_SOURCE_STYLUS)
9768 .buttonState(
9769 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9770 .pointer(PointerBuilder(0, ToolType::STYLUS)
9771 .x(50)
9772 .y(50))
9773 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009774 break;
9775 case AINPUT_SOURCE_MOUSE:
9776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009777 injectMotionEvent(*mDispatcher,
9778 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9779 AINPUT_SOURCE_MOUSE)
9780 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9781 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9782 ToolType::MOUSE)
9783 .x(50)
9784 .y(50))
9785 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009786 break;
9787 default:
9788 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9789 }
arthurhungb89ccb02020-12-30 16:19:01 +08009790
9791 // Window should receive motion event.
9792 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009793 // Spy window should also receive motion event
9794 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009795 }
9796
9797 // Start performing drag, we will create a drag window and transfer touch to it.
9798 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9799 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009800 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009801 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009802 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009803 }
arthurhungb89ccb02020-12-30 16:19:01 +08009804
9805 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009806 mDragWindow =
9807 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009808 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009809 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9810 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9811 {},
9812 0,
9813 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009814
9815 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009816 bool transferred =
9817 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009818 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009819 if (transferred) {
9820 mWindow->consumeMotionCancel();
9821 mDragWindow->consumeMotionDown();
9822 }
9823 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009824 }
9825};
9826
9827TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009828 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009829
9830 // Move on window.
9831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009832 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009833 ADISPLAY_ID_DEFAULT, {50, 50}))
9834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9835 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9836 mWindow->consumeDragEvent(false, 50, 50);
9837 mSecondWindow->assertNoEvents();
9838
9839 // Move to another window.
9840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009841 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009842 ADISPLAY_ID_DEFAULT, {150, 50}))
9843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9844 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9845 mWindow->consumeDragEvent(true, 150, 50);
9846 mSecondWindow->consumeDragEvent(false, 50, 50);
9847
9848 // Move back to original window.
9849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009850 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009851 ADISPLAY_ID_DEFAULT, {50, 50}))
9852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9853 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9854 mWindow->consumeDragEvent(false, 50, 50);
9855 mSecondWindow->consumeDragEvent(true, -50, 50);
9856
9857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009858 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9859 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9861 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9862 mWindow->assertNoEvents();
9863 mSecondWindow->assertNoEvents();
9864}
9865
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009866TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009867 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009868
9869 // No cancel event after drag start
9870 mSpyWindow->assertNoEvents();
9871
9872 const MotionEvent secondFingerDownEvent =
9873 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9874 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009875 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9876 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009877 .build();
9878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009879 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009880 InputEventInjectionSync::WAIT_FOR_RESULT))
9881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9882
9883 // Receives cancel for first pointer after next pointer down
9884 mSpyWindow->consumeMotionCancel();
9885 mSpyWindow->consumeMotionDown();
9886
9887 mSpyWindow->assertNoEvents();
9888}
9889
arthurhungf452d0b2021-01-06 00:19:52 +08009890TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009891 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009892
9893 // Move on window.
9894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009895 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009896 ADISPLAY_ID_DEFAULT, {50, 50}))
9897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9898 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9899 mWindow->consumeDragEvent(false, 50, 50);
9900 mSecondWindow->assertNoEvents();
9901
9902 // Move to another window.
9903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009904 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009905 ADISPLAY_ID_DEFAULT, {150, 50}))
9906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9907 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9908 mWindow->consumeDragEvent(true, 150, 50);
9909 mSecondWindow->consumeDragEvent(false, 50, 50);
9910
9911 // drop to another window.
9912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009913 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009914 {150, 50}))
9915 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9916 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009917 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009918 mWindow->assertNoEvents();
9919 mSecondWindow->assertNoEvents();
9920}
9921
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009922TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9923 startDrag();
9924
9925 // No cancel event after drag start
9926 mSpyWindow->assertNoEvents();
9927
9928 const MotionEvent secondFingerDownEvent =
9929 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9930 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9931 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9932 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9933 .build();
9934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9935 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9936 InputEventInjectionSync::WAIT_FOR_RESULT))
9937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9938
9939 // Receives cancel for first pointer after next pointer down
9940 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08009941 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009942 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9943
9944 mSpyWindow->assertNoEvents();
9945
9946 // Spy window calls pilfer pointers
9947 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9948 mDragWindow->assertNoEvents();
9949
9950 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009951 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009952 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9953 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9954 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9955 .build();
9956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009957 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009958 InputEventInjectionSync::WAIT_FOR_RESULT))
9959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9960
9961 // Drag window should still receive the new event
9962 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9963 mDragWindow->assertNoEvents();
9964}
9965
arthurhung6d4bed92021-03-17 11:59:33 +08009966TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009967 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009968
9969 // Move on window and keep button pressed.
9970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009971 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009972 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9973 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009974 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009975 .build()))
9976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9977 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9978 mWindow->consumeDragEvent(false, 50, 50);
9979 mSecondWindow->assertNoEvents();
9980
9981 // Move to another window and release button, expect to drop item.
9982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009983 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009984 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9985 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009987 .build()))
9988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9989 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9990 mWindow->assertNoEvents();
9991 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009992 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08009993
9994 // nothing to the window.
9995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009996 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009997 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
9998 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009999 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010000 .build()))
10001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10002 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10003 mWindow->assertNoEvents();
10004 mSecondWindow->assertNoEvents();
10005}
10006
Arthur Hung54745652022-04-20 07:17:41 +000010007TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010008 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010009
10010 // Set second window invisible.
10011 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010012 mDispatcher->onWindowInfosChanged(
10013 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010014
10015 // Move on window.
10016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010017 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010018 ADISPLAY_ID_DEFAULT, {50, 50}))
10019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10020 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10021 mWindow->consumeDragEvent(false, 50, 50);
10022 mSecondWindow->assertNoEvents();
10023
10024 // Move to another window.
10025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010026 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010027 ADISPLAY_ID_DEFAULT, {150, 50}))
10028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10029 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10030 mWindow->consumeDragEvent(true, 150, 50);
10031 mSecondWindow->assertNoEvents();
10032
10033 // drop to another window.
10034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010035 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010036 {150, 50}))
10037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10038 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010039 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010040 mWindow->assertNoEvents();
10041 mSecondWindow->assertNoEvents();
10042}
10043
Arthur Hung54745652022-04-20 07:17:41 +000010044TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010045 // Ensure window could track pointerIds if it didn't support split touch.
10046 mWindow->setPreventSplitting(true);
10047
Arthur Hung54745652022-04-20 07:17:41 +000010048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010049 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010050 {50, 50}))
10051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10052 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10053
10054 const MotionEvent secondFingerDownEvent =
10055 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10056 .displayId(ADISPLAY_ID_DEFAULT)
10057 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010058 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10059 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010060 .build();
10061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010062 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010063 InputEventInjectionSync::WAIT_FOR_RESULT))
10064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010065 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010066
10067 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010068 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010069}
10070
10071TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10072 // First down on second window.
10073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010074 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010075 {150, 50}))
10076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10077
10078 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10079
10080 // Second down on first window.
10081 const MotionEvent secondFingerDownEvent =
10082 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10083 .displayId(ADISPLAY_ID_DEFAULT)
10084 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010085 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10086 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010087 .build();
10088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010089 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010090 InputEventInjectionSync::WAIT_FOR_RESULT))
10091 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10092 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10093
10094 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010095 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010096
10097 // Move on window.
10098 const MotionEvent secondFingerMoveEvent =
10099 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10100 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010101 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10102 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010103 .build();
10104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010105 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010106 InputEventInjectionSync::WAIT_FOR_RESULT));
10107 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10108 mWindow->consumeDragEvent(false, 50, 50);
10109 mSecondWindow->consumeMotionMove();
10110
10111 // Release the drag pointer should perform drop.
10112 const MotionEvent secondFingerUpEvent =
10113 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10114 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010115 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10116 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010117 .build();
10118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010119 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010120 InputEventInjectionSync::WAIT_FOR_RESULT));
10121 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010122 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010123 mWindow->assertNoEvents();
10124 mSecondWindow->consumeMotionMove();
10125}
10126
Arthur Hung3915c1f2022-05-31 07:17:17 +000010127TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010128 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010129
10130 // Update window of second display.
10131 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010132 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010133 mDispatcher->onWindowInfosChanged(
10134 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10135 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10136 {},
10137 0,
10138 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010139
10140 // Let second display has a touch state.
10141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010142 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010143 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10144 AINPUT_SOURCE_TOUCHSCREEN)
10145 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010146 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010147 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010148 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010149 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010150 mDispatcher->onWindowInfosChanged(
10151 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10152 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10153 {},
10154 0,
10155 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010156
10157 // Move on window.
10158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010159 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010160 ADISPLAY_ID_DEFAULT, {50, 50}))
10161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10162 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10163 mWindow->consumeDragEvent(false, 50, 50);
10164 mSecondWindow->assertNoEvents();
10165
10166 // Move to another window.
10167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010168 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010169 ADISPLAY_ID_DEFAULT, {150, 50}))
10170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10171 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10172 mWindow->consumeDragEvent(true, 150, 50);
10173 mSecondWindow->consumeDragEvent(false, 50, 50);
10174
10175 // drop to another window.
10176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010177 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010178 {150, 50}))
10179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10180 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010181 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010182 mWindow->assertNoEvents();
10183 mSecondWindow->assertNoEvents();
10184}
10185
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010186TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10187 startDrag(true, AINPUT_SOURCE_MOUSE);
10188 // Move on window.
10189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010190 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010191 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10192 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010193 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010194 .x(50)
10195 .y(50))
10196 .build()))
10197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10198 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10199 mWindow->consumeDragEvent(false, 50, 50);
10200 mSecondWindow->assertNoEvents();
10201
10202 // Move to another window.
10203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010204 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010205 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10206 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010207 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010208 .x(150)
10209 .y(50))
10210 .build()))
10211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10212 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10213 mWindow->consumeDragEvent(true, 150, 50);
10214 mSecondWindow->consumeDragEvent(false, 50, 50);
10215
10216 // drop to another window.
10217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010218 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010219 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10220 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010221 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010222 .x(150)
10223 .y(50))
10224 .build()))
10225 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10226 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010227 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010228 mWindow->assertNoEvents();
10229 mSecondWindow->assertNoEvents();
10230}
10231
Linnan Li5af92f92023-07-14 14:36:22 +080010232/**
10233 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10234 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10235 */
10236TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10237 // Down on second window
10238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10239 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10240 {150, 50}))
10241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10242
10243 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10244 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10245
10246 // Down on first window
10247 const MotionEvent secondFingerDownEvent =
10248 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10249 .displayId(ADISPLAY_ID_DEFAULT)
10250 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10251 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10252 .build();
10253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10254 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10255 InputEventInjectionSync::WAIT_FOR_RESULT))
10256 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10257 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10258 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10259 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10260
10261 // Start drag on first window
10262 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10263
10264 // Trigger cancel
10265 mDispatcher->cancelCurrentTouch();
10266 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10267 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10268 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10269
10270 ASSERT_TRUE(mDispatcher->waitForIdle());
10271 // The D&D finished with nullptr
10272 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10273
10274 // Remove drag window
10275 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10276
10277 // Inject a simple gesture, ensure dispatcher not crashed
10278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10279 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10280 PointF{50, 50}))
10281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10282 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10283
10284 const MotionEvent moveEvent =
10285 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10286 .displayId(ADISPLAY_ID_DEFAULT)
10287 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10288 .build();
10289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10290 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10291 InputEventInjectionSync::WAIT_FOR_RESULT))
10292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10293 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10294
10295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10296 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10297 {50, 50}))
10298 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10299 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10300}
10301
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010302TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10303 // Start hovering over the window.
10304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10305 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10306 ADISPLAY_ID_DEFAULT, {50, 50}));
10307
10308 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10309 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10310
10311 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10312 << "Drag and drop should not work with a hovering pointer";
10313}
10314
Vishnu Nair062a8672021-09-03 16:07:44 -070010315class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10316
10317TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010319 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10320 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010321 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010322 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10323 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010324 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010325 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010326 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010327
10328 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010329 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010330 window->assertNoEvents();
10331
Prabir Pradhan678438e2023-04-13 19:32:51 +000010332 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10333 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010334 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10335 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010336 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010337 window->assertNoEvents();
10338
10339 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010340 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010341 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010342
Prabir Pradhan678438e2023-04-13 19:32:51 +000010343 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010344 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10345
Prabir Pradhan678438e2023-04-13 19:32:51 +000010346 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010348 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10349 window->assertNoEvents();
10350}
10351
10352TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10353 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10354 std::make_shared<FakeApplicationHandle>();
10355 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010356 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10357 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010358 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010359 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010360 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010362 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10363 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010364 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010365 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010366 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10367 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010368 mDispatcher->onWindowInfosChanged(
10369 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010370 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010371 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010372
10373 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010374 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010375 window->assertNoEvents();
10376
Prabir Pradhan678438e2023-04-13 19:32:51 +000010377 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10378 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010379 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10380 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010381 window->assertNoEvents();
10382
10383 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010384 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010385 mDispatcher->onWindowInfosChanged(
10386 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010387
Prabir Pradhan678438e2023-04-13 19:32:51 +000010388 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010389 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10390
Prabir Pradhan678438e2023-04-13 19:32:51 +000010391 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10392 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010393 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10394 window->assertNoEvents();
10395}
10396
10397TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10398 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10399 std::make_shared<FakeApplicationHandle>();
10400 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010401 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10402 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010403 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010404 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010405 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010407 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10408 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010409 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010410 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010411 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10412 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010413 mDispatcher->onWindowInfosChanged(
10414 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010415 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010416 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010417
10418 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010419 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010420 window->assertNoEvents();
10421
Prabir Pradhan678438e2023-04-13 19:32:51 +000010422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10423 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010424 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10425 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010426 window->assertNoEvents();
10427
10428 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010429 mDispatcher->onWindowInfosChanged(
10430 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010431
Prabir Pradhan678438e2023-04-13 19:32:51 +000010432 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010433 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10434
Prabir Pradhan678438e2023-04-13 19:32:51 +000010435 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10436 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010437 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10438 window->assertNoEvents();
10439}
10440
Antonio Kantekf16f2832021-09-28 04:39:20 +000010441class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10442protected:
10443 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010444 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010445 sp<FakeWindowHandle> mWindow;
10446 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010447 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010448
10449 void SetUp() override {
10450 InputDispatcherTest::SetUp();
10451
10452 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010453 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010454 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010455 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010456 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010457 mSecondWindow =
10458 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010459 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010460 mThirdWindow =
10461 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10462 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10463 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010464
10465 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010466 mDispatcher->onWindowInfosChanged(
10467 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10468 {},
10469 0,
10470 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010471 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010472 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010473
Antonio Kantek15beb512022-06-13 22:35:41 +000010474 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010475 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010476 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010477 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10478 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010479 mThirdWindow->assertNoEvents();
10480 }
10481
10482 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10483 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010484 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010485 SECOND_DISPLAY_ID)) {
10486 mWindow->assertNoEvents();
10487 mSecondWindow->assertNoEvents();
10488 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010489 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010490 }
10491
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010492 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010493 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010494 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10495 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010496 mWindow->consumeTouchModeEvent(inTouchMode);
10497 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010498 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010499 }
10500};
10501
Antonio Kantek26defcf2022-02-08 01:12:27 +000010502TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010503 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010504 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10505 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010506 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010507}
10508
Antonio Kantek26defcf2022-02-08 01:12:27 +000010509TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10510 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010511 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010512 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010513 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010514 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010515 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010516 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010517 mWindow->assertNoEvents();
10518 mSecondWindow->assertNoEvents();
10519}
10520
10521TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10522 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010523 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010524 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010525 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010526 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010527 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010528}
10529
Antonio Kantekf16f2832021-09-28 04:39:20 +000010530TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010531 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010532 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10533 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010534 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010535 mWindow->assertNoEvents();
10536 mSecondWindow->assertNoEvents();
10537}
10538
Antonio Kantek15beb512022-06-13 22:35:41 +000010539TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10540 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10541 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10542 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010543 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010544 mWindow->assertNoEvents();
10545 mSecondWindow->assertNoEvents();
10546 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10547}
10548
Antonio Kantek48710e42022-03-24 14:19:30 -070010549TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10550 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10552 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010553 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10554 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10555
10556 // Then remove focus.
10557 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010558 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010559
10560 // Assert that caller can switch touch mode by owning one of the last interacted window.
10561 const WindowInfo& windowInfo = *mWindow->getInfo();
10562 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10563 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010564 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010565}
10566
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010567class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10568public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010569 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010570 std::shared_ptr<FakeApplicationHandle> application =
10571 std::make_shared<FakeApplicationHandle>();
10572 std::string name = "Fake Spy ";
10573 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010574 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10575 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010576 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010577 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010578 return spy;
10579 }
10580
10581 sp<FakeWindowHandle> createForeground() {
10582 std::shared_ptr<FakeApplicationHandle> application =
10583 std::make_shared<FakeApplicationHandle>();
10584 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010585 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10586 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010587 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010588 return window;
10589 }
10590
10591private:
10592 int mSpyCount{0};
10593};
10594
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010595using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010596/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010597 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10598 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010599TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010600 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010601 ScopedSilentDeath _silentDeath;
10602
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010603 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010604 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010605 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010606 ".* not a trusted overlay");
10607}
10608
10609/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010610 * Input injection into a display with a spy window but no foreground windows should succeed.
10611 */
10612TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010613 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010614 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010615
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 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10620}
10621
10622/**
10623 * Verify the order in which different input windows receive events. The touched foreground window
10624 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10625 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10626 * receive events before ones belows it.
10627 *
10628 * Here, we set up a scenario with four windows in the following Z order from the top:
10629 * spy1, spy2, window, spy3.
10630 * We then inject an event and verify that the foreground "window" receives it first, followed by
10631 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10632 * window.
10633 */
10634TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10635 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010636 auto spy1 = createSpy();
10637 auto spy2 = createSpy();
10638 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010639 mDispatcher->onWindowInfosChanged(
10640 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010641 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10642 const size_t numChannels = channels.size();
10643
Michael Wright8e9a8562022-02-09 13:44:29 +000010644 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010645 if (!epollFd.ok()) {
10646 FAIL() << "Failed to create epoll fd";
10647 }
10648
10649 for (size_t i = 0; i < numChannels; i++) {
10650 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10651 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10652 FAIL() << "Failed to add fd to epoll";
10653 }
10654 }
10655
10656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010657 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10659
10660 std::vector<size_t> eventOrder;
10661 std::vector<struct epoll_event> events(numChannels);
10662 for (;;) {
10663 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10664 (100ms).count());
10665 if (nFds < 0) {
10666 FAIL() << "Failed to call epoll_wait";
10667 }
10668 if (nFds == 0) {
10669 break; // epoll_wait timed out
10670 }
10671 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010672 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010673 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010674 channels[i]->consumeMotionDown();
10675 }
10676 }
10677
10678 // Verify the order in which the events were received.
10679 EXPECT_EQ(3u, eventOrder.size());
10680 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10681 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10682 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10683}
10684
10685/**
10686 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10687 */
10688TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10689 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010690 auto spy = createSpy();
10691 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010692 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010693
10694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010695 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10697 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10698 spy->assertNoEvents();
10699}
10700
10701/**
10702 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10703 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10704 * to the window.
10705 */
10706TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10707 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010708 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010709 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010710 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010711
10712 // Inject an event outside the spy window's touchable region.
10713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010714 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10716 window->consumeMotionDown();
10717 spy->assertNoEvents();
10718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010719 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10721 window->consumeMotionUp();
10722 spy->assertNoEvents();
10723
10724 // Inject an event inside the spy window's touchable region.
10725 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010726 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010727 {5, 10}))
10728 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10729 window->consumeMotionDown();
10730 spy->consumeMotionDown();
10731}
10732
10733/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010734 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010735 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010736 */
10737TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10738 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010739 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010740 auto spy = createSpy();
10741 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010742 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010743 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010744 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010745
10746 // Inject an event outside the spy window's frame and touchable region.
10747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010748 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010749 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10751 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010752 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010753}
10754
10755/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010756 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10757 * pointers that are down within its bounds.
10758 */
10759TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10760 auto windowLeft = createForeground();
10761 windowLeft->setFrame({0, 0, 100, 200});
10762 auto windowRight = createForeground();
10763 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010764 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010765 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010766 mDispatcher->onWindowInfosChanged(
10767 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010768
10769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010770 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010771 {50, 50}))
10772 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10773 windowLeft->consumeMotionDown();
10774 spy->consumeMotionDown();
10775
10776 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010777 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010778 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010779 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10780 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010781 .build();
10782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010783 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010784 InputEventInjectionSync::WAIT_FOR_RESULT))
10785 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10786 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010787 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010788}
10789
10790/**
10791 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10792 * the spy should receive the second pointer with ACTION_DOWN.
10793 */
10794TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10795 auto window = createForeground();
10796 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010797 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010798 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010799 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010800
10801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010802 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010803 {50, 50}))
10804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10805 window->consumeMotionDown();
10806 spyRight->assertNoEvents();
10807
10808 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010809 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010810 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010811 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10812 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010813 .build();
10814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010815 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010816 InputEventInjectionSync::WAIT_FOR_RESULT))
10817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010818 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010819 spyRight->consumeMotionDown();
10820}
10821
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010822/**
10823 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10824 * windows should be allowed to control split touch.
10825 */
10826TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010827 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010828 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010829 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010830 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010831
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010832 auto window = createForeground();
10833 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010834
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010835 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010836
10837 // First finger down, no window touched.
10838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010840 {100, 200}))
10841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10842 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10843 window->assertNoEvents();
10844
10845 // Second finger down on window, the window should receive touch down.
10846 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010847 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010848 .displayId(ADISPLAY_ID_DEFAULT)
10849 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010850 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10851 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010852 .build();
10853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010854 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010855 InputEventInjectionSync::WAIT_FOR_RESULT))
10856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10857
10858 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010859 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010860}
10861
10862/**
10863 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10864 * do not receive key events.
10865 */
10866TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010867 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010868 spy->setFocusable(false);
10869
10870 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010871 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010872 setFocusedWindow(window);
10873 window->consumeFocusEvent(true);
10874
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010876 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10877 window->consumeKeyDown(ADISPLAY_ID_NONE);
10878
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010880 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10881 window->consumeKeyUp(ADISPLAY_ID_NONE);
10882
10883 spy->assertNoEvents();
10884}
10885
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010886using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10887
10888/**
10889 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10890 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10891 */
10892TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10893 auto window = createForeground();
10894 auto spy1 = createSpy();
10895 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010896 mDispatcher->onWindowInfosChanged(
10897 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010898
10899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010900 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10902 window->consumeMotionDown();
10903 spy1->consumeMotionDown();
10904 spy2->consumeMotionDown();
10905
10906 // Pilfer pointers from the second spy window.
10907 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10908 spy2->assertNoEvents();
10909 spy1->consumeMotionCancel();
10910 window->consumeMotionCancel();
10911
10912 // The rest of the gesture should only be sent to the second spy window.
10913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010914 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010915 ADISPLAY_ID_DEFAULT))
10916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10917 spy2->consumeMotionMove();
10918 spy1->assertNoEvents();
10919 window->assertNoEvents();
10920}
10921
10922/**
10923 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10924 * in the middle of the gesture.
10925 */
10926TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10927 auto window = createForeground();
10928 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010929 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010930
10931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010932 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010933 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10934 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10935 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10936
10937 window->releaseChannel();
10938
10939 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10940
10941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010942 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10944 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10945}
10946
10947/**
10948 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10949 * the spy, but not to any other windows.
10950 */
10951TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10952 auto spy = createSpy();
10953 auto window = createForeground();
10954
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010955 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010956
10957 // First finger down on the window and the spy.
10958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010959 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010960 {100, 200}))
10961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10962 spy->consumeMotionDown();
10963 window->consumeMotionDown();
10964
10965 // Spy window pilfers the pointers.
10966 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10967 window->consumeMotionCancel();
10968
10969 // Second finger down on the window and spy, but the window should not receive the pointer down.
10970 const MotionEvent secondFingerDownEvent =
10971 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10972 .displayId(ADISPLAY_ID_DEFAULT)
10973 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010974 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10975 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010976 .build();
10977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010978 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010979 InputEventInjectionSync::WAIT_FOR_RESULT))
10980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10981
Harry Cutts33476232023-01-30 19:57:29 +000010982 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010983
10984 // Third finger goes down outside all windows, so injection should fail.
10985 const MotionEvent thirdFingerDownEvent =
10986 MotionEventBuilder(POINTER_2_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(100).y(200))
10990 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10991 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010992 .build();
10993 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010994 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010995 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010996 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010997
10998 spy->assertNoEvents();
10999 window->assertNoEvents();
11000}
11001
11002/**
11003 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11004 */
11005TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11006 auto spy = createSpy();
11007 spy->setFrame(Rect(0, 0, 100, 100));
11008 auto window = createForeground();
11009 window->setFrame(Rect(0, 0, 200, 200));
11010
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011011 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011012
11013 // First finger down on the window only
11014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011015 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011016 {150, 150}))
11017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11018 window->consumeMotionDown();
11019
11020 // Second finger down on the spy and window
11021 const MotionEvent secondFingerDownEvent =
11022 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11023 .displayId(ADISPLAY_ID_DEFAULT)
11024 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011025 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11026 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011027 .build();
11028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011029 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011030 InputEventInjectionSync::WAIT_FOR_RESULT))
11031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11032 spy->consumeMotionDown();
11033 window->consumeMotionPointerDown(1);
11034
11035 // Third finger down on the spy and window
11036 const MotionEvent thirdFingerDownEvent =
11037 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11038 .displayId(ADISPLAY_ID_DEFAULT)
11039 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011040 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11041 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11042 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011043 .build();
11044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011045 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011046 InputEventInjectionSync::WAIT_FOR_RESULT))
11047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11048 spy->consumeMotionPointerDown(1);
11049 window->consumeMotionPointerDown(2);
11050
11051 // Spy window pilfers the pointers.
11052 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011053 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11054 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011055
11056 spy->assertNoEvents();
11057 window->assertNoEvents();
11058}
11059
11060/**
11061 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11062 * other windows should be canceled. If this results in the cancellation of all pointers for some
11063 * window, then that window should receive ACTION_CANCEL.
11064 */
11065TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11066 auto spy = createSpy();
11067 spy->setFrame(Rect(0, 0, 100, 100));
11068 auto window = createForeground();
11069 window->setFrame(Rect(0, 0, 200, 200));
11070
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011071 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011072
11073 // First finger down on both spy and window
11074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011075 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011076 {10, 10}))
11077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11078 window->consumeMotionDown();
11079 spy->consumeMotionDown();
11080
11081 // Second finger down on the spy and window
11082 const MotionEvent secondFingerDownEvent =
11083 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11084 .displayId(ADISPLAY_ID_DEFAULT)
11085 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011086 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11087 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011088 .build();
11089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011090 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011091 InputEventInjectionSync::WAIT_FOR_RESULT))
11092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11093 spy->consumeMotionPointerDown(1);
11094 window->consumeMotionPointerDown(1);
11095
11096 // Spy window pilfers the pointers.
11097 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11098 window->consumeMotionCancel();
11099
11100 spy->assertNoEvents();
11101 window->assertNoEvents();
11102}
11103
11104/**
11105 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11106 * be sent to other windows
11107 */
11108TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11109 auto spy = createSpy();
11110 spy->setFrame(Rect(0, 0, 100, 100));
11111 auto window = createForeground();
11112 window->setFrame(Rect(0, 0, 200, 200));
11113
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011114 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011115
11116 // First finger down on both window and spy
11117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011119 {10, 10}))
11120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11121 window->consumeMotionDown();
11122 spy->consumeMotionDown();
11123
11124 // Spy window pilfers the pointers.
11125 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11126 window->consumeMotionCancel();
11127
11128 // Second finger down on the window only
11129 const MotionEvent secondFingerDownEvent =
11130 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11131 .displayId(ADISPLAY_ID_DEFAULT)
11132 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011133 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11134 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011135 .build();
11136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011137 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011138 InputEventInjectionSync::WAIT_FOR_RESULT))
11139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11140 window->consumeMotionDown();
11141 window->assertNoEvents();
11142
11143 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11144 spy->consumeMotionMove();
11145 spy->assertNoEvents();
11146}
11147
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011148/**
11149 * A window on the left and a window on the right. Also, a spy window that's above all of the
11150 * windows, and spanning both left and right windows.
11151 * Send simultaneous motion streams from two different devices, one to the left window, and another
11152 * to the right window.
11153 * Pilfer from spy window.
11154 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11155 */
11156TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11157 sp<FakeWindowHandle> spy = createSpy();
11158 spy->setFrame(Rect(0, 0, 200, 200));
11159 sp<FakeWindowHandle> leftWindow = createForeground();
11160 leftWindow->setFrame(Rect(0, 0, 100, 100));
11161
11162 sp<FakeWindowHandle> rightWindow = createForeground();
11163 rightWindow->setFrame(Rect(100, 0, 200, 100));
11164
11165 constexpr int32_t stylusDeviceId = 1;
11166 constexpr int32_t touchDeviceId = 2;
11167
11168 mDispatcher->onWindowInfosChanged(
11169 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11170
11171 // Stylus down on left window and spy
11172 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11173 .deviceId(stylusDeviceId)
11174 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11175 .build());
11176 leftWindow->consumeMotionEvent(
11177 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11178 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11179
11180 // Finger down on right window and spy - but spy already has stylus
11181 mDispatcher->notifyMotion(
11182 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11183 .deviceId(touchDeviceId)
11184 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11185 .build());
11186 rightWindow->consumeMotionEvent(
11187 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011188 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011189
11190 // Act: pilfer from spy. Spy is currently receiving touch events.
11191 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011192 leftWindow->consumeMotionEvent(
11193 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011194 rightWindow->consumeMotionEvent(
11195 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11196
11197 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11198 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11199 .deviceId(stylusDeviceId)
11200 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11201 .build());
11202 mDispatcher->notifyMotion(
11203 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11204 .deviceId(touchDeviceId)
11205 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11206 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011207 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011208
11209 spy->assertNoEvents();
11210 leftWindow->assertNoEvents();
11211 rightWindow->assertNoEvents();
11212}
11213
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011214TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11215 auto window = createForeground();
11216 auto spy = createSpy();
11217 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11218
11219 mDispatcher->notifyMotion(
11220 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11221 .deviceId(1)
11222 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11223 .build());
11224 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11225 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11226
11227 // Pilfer pointers from the spy window should fail.
11228 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11229 spy->assertNoEvents();
11230 window->assertNoEvents();
11231}
11232
Prabir Pradhand65552b2021-10-07 11:23:50 -070011233class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11234public:
11235 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11236 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11237 std::make_shared<FakeApplicationHandle>();
11238 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011239 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11240 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011241 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011242 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011243 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011244 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011245 overlay->setTrustedOverlay(true);
11246
11247 std::shared_ptr<FakeApplicationHandle> application =
11248 std::make_shared<FakeApplicationHandle>();
11249 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011250 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11251 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011252 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011253 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011254
11255 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011256 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011257 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011258 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011259 return {std::move(overlay), std::move(window)};
11260 }
11261
11262 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011263 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011264 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011265 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011266 }
11267
11268 void sendStylusEvent(int32_t action) {
11269 NotifyMotionArgs motionArgs =
11270 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11271 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011272 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011273 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011274 }
11275};
11276
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011277using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11278
11279TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011280 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011281 ScopedSilentDeath _silentDeath;
11282
Prabir Pradhand65552b2021-10-07 11:23:50 -070011283 auto [overlay, window] = setupStylusOverlayScenario();
11284 overlay->setTrustedOverlay(false);
11285 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011286 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11287 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011288 ".* not a trusted overlay");
11289}
11290
11291TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11292 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011293 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011294
11295 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11296 overlay->consumeMotionDown();
11297 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11298 overlay->consumeMotionUp();
11299
11300 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11301 window->consumeMotionDown();
11302 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11303 window->consumeMotionUp();
11304
11305 overlay->assertNoEvents();
11306 window->assertNoEvents();
11307}
11308
11309TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11310 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011311 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011312 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011313
11314 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11315 overlay->consumeMotionDown();
11316 window->consumeMotionDown();
11317 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11318 overlay->consumeMotionUp();
11319 window->consumeMotionUp();
11320
11321 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11322 window->consumeMotionDown();
11323 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11324 window->consumeMotionUp();
11325
11326 overlay->assertNoEvents();
11327 window->assertNoEvents();
11328}
11329
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011330/**
11331 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11332 * The scenario is as follows:
11333 * - The stylus interceptor overlay is configured as a spy window.
11334 * - The stylus interceptor spy receives the start of a new stylus gesture.
11335 * - It pilfers pointers and then configures itself to no longer be a spy.
11336 * - The stylus interceptor continues to receive the rest of the gesture.
11337 */
11338TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11339 auto [overlay, window] = setupStylusOverlayScenario();
11340 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011341 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011342
11343 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11344 overlay->consumeMotionDown();
11345 window->consumeMotionDown();
11346
11347 // The interceptor pilfers the pointers.
11348 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11349 window->consumeMotionCancel();
11350
11351 // The interceptor configures itself so that it is no longer a spy.
11352 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011353 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011354
11355 // It continues to receive the rest of the stylus gesture.
11356 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11357 overlay->consumeMotionMove();
11358 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11359 overlay->consumeMotionUp();
11360
11361 window->assertNoEvents();
11362}
11363
Prabir Pradhan5735a322022-04-11 17:23:34 +000011364struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011365 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011366 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011367 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11368 std::unique_ptr<InputDispatcher>& mDispatcher;
11369
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011370 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011371 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11372
11373 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011374 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011375 ADISPLAY_ID_DEFAULT, {100, 200},
11376 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11377 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11378 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11379 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11380 }
11381
11382 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011383 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011384 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011385 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011386 mPolicyFlags);
11387 }
11388
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011389 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011390 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11391 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011392 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11393 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011394 window->setOwnerInfo(mPid, mUid);
11395 return window;
11396 }
11397};
11398
11399using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11400
11401TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011402 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011403 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011404 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011405
11406 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11407 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11408 window->consumeMotionDown();
11409
11410 setFocusedWindow(window);
11411 window->consumeFocusEvent(true);
11412
11413 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11414 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11415 window->consumeKeyDown(ADISPLAY_ID_NONE);
11416}
11417
11418TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011419 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011420 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011421 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011422
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011423 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011424 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11425 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11426
11427 setFocusedWindow(window);
11428 window->consumeFocusEvent(true);
11429
11430 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11431 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11432 window->assertNoEvents();
11433}
11434
11435TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011436 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011437 auto window = owner.createWindow("Owned window");
11438 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011439 spy->setSpy(true);
11440 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011441 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011442
11443 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11444 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11445 spy->consumeMotionDown();
11446 window->consumeMotionDown();
11447}
11448
11449TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011450 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011451 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011452
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011453 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011454 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011455 randosSpy->setSpy(true);
11456 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011457 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011458
11459 // The event is targeted at owner's window, so injection should succeed, but the spy should
11460 // not receive the event.
11461 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11462 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11463 randosSpy->assertNoEvents();
11464 window->consumeMotionDown();
11465}
11466
11467TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011468 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011469 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011470
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011471 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011472 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011473 randosSpy->setSpy(true);
11474 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011475 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011476
11477 // A user that has injection permission can inject into any window.
11478 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011479 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011480 ADISPLAY_ID_DEFAULT));
11481 randosSpy->consumeMotionDown();
11482 window->consumeMotionDown();
11483
11484 setFocusedWindow(randosSpy);
11485 randosSpy->consumeFocusEvent(true);
11486
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011487 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011488 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11489 window->assertNoEvents();
11490}
11491
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011492TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011493 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011494 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011495
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011496 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011497 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011498 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11499 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011500 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011501
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011502 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011503 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11504 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11505 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011506 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011507}
11508
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011509using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11510
11511TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11513
11514 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11515 ADISPLAY_ID_DEFAULT);
11516 left->setFrame(Rect(0, 0, 100, 100));
11517 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11518 "Right Window", ADISPLAY_ID_DEFAULT);
11519 right->setFrame(Rect(100, 0, 200, 100));
11520 sp<FakeWindowHandle> spy =
11521 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11522 spy->setFrame(Rect(0, 0, 200, 100));
11523 spy->setTrustedOverlay(true);
11524 spy->setSpy(true);
11525
11526 mDispatcher->onWindowInfosChanged(
11527 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11528
11529 // Hover into the left window.
11530 mDispatcher->notifyMotion(
11531 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11532 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11533 .build());
11534
11535 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11536 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11537
11538 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11539 /*pointerId=*/0));
11540 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11541 /*pointerId=*/0));
11542 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11543 /*pointerId=*/0));
11544
11545 // Hover move to the right window.
11546 mDispatcher->notifyMotion(
11547 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11548 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11549 .build());
11550
11551 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11552 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11553 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11554
11555 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11556 /*pointerId=*/0));
11557 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11558 /*pointerId=*/0));
11559 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11560 /*pointerId=*/0));
11561
11562 // Stop hovering.
11563 mDispatcher->notifyMotion(
11564 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11565 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11566 .build());
11567
11568 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11569 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11570
11571 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11572 /*pointerId=*/0));
11573 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11574 /*pointerId=*/0));
11575 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11576 /*pointerId=*/0));
11577}
11578
11579TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11580 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11581
11582 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11583 ADISPLAY_ID_DEFAULT);
11584 left->setFrame(Rect(0, 0, 100, 100));
11585 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11586 "Right Window", ADISPLAY_ID_DEFAULT);
11587 right->setFrame(Rect(100, 0, 200, 100));
11588 sp<FakeWindowHandle> spy =
11589 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11590 spy->setFrame(Rect(0, 0, 200, 100));
11591 spy->setTrustedOverlay(true);
11592 spy->setSpy(true);
11593
11594 mDispatcher->onWindowInfosChanged(
11595 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11596
11597 // First pointer down on left window.
11598 mDispatcher->notifyMotion(
11599 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11600 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11601 .build());
11602
11603 left->consumeMotionDown();
11604 spy->consumeMotionDown();
11605
11606 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11607 /*pointerId=*/0));
11608 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11609 /*pointerId=*/0));
11610 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11611 /*pointerId=*/0));
11612
11613 // Second pointer down on right window.
11614 mDispatcher->notifyMotion(
11615 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11616 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11617 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11618 .build());
11619
11620 left->consumeMotionMove();
11621 right->consumeMotionDown();
11622 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11623
11624 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11625 /*pointerId=*/0));
11626 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11627 /*pointerId=*/0));
11628 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11629 /*pointerId=*/0));
11630 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11631 /*pointerId=*/1));
11632 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11633 /*pointerId=*/1));
11634 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11635 /*pointerId=*/1));
11636
11637 // Second pointer up.
11638 mDispatcher->notifyMotion(
11639 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11640 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11641 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11642 .build());
11643
11644 left->consumeMotionMove();
11645 right->consumeMotionUp();
11646 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11647
11648 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11649 /*pointerId=*/0));
11650 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11651 /*pointerId=*/0));
11652 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11653 /*pointerId=*/0));
11654 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11655 /*pointerId=*/1));
11656 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11657 /*pointerId=*/1));
11658 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11659 /*pointerId=*/1));
11660
11661 // First pointer up.
11662 mDispatcher->notifyMotion(
11663 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11664 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11665 .build());
11666
11667 left->consumeMotionUp();
11668 spy->consumeMotionUp();
11669
11670 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11671 /*pointerId=*/0));
11672 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11673 /*pointerId=*/0));
11674 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11675 /*pointerId=*/0));
11676}
11677
11678TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11680
11681 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11682 ADISPLAY_ID_DEFAULT);
11683 left->setFrame(Rect(0, 0, 100, 100));
11684 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11685 "Right Window", ADISPLAY_ID_DEFAULT);
11686 right->setFrame(Rect(100, 0, 200, 100));
11687
11688 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11689
11690 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11691 /*pointerId=*/0));
11692 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11693 /*pointerId=*/0));
11694
11695 // Hover move into the window.
11696 mDispatcher->notifyMotion(
11697 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11698 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11699 .rawXCursorPosition(50)
11700 .rawYCursorPosition(50)
11701 .deviceId(DEVICE_ID)
11702 .build());
11703
11704 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11705
11706 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11707 /*pointerId=*/0));
11708
11709 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11710 mDispatcher->notifyMotion(
11711 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11712 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11713 .rawXCursorPosition(51)
11714 .rawYCursorPosition(50)
11715 .deviceId(SECOND_DEVICE_ID)
11716 .build());
11717
11718 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11719 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11720
11721 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11722 // a HOVER_EXIT from the first device.
11723 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11724 /*pointerId=*/0));
11725 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11726 SECOND_DEVICE_ID,
11727 /*pointerId=*/0));
11728
11729 // Move the mouse outside the window. Document the current behavior, where the window does not
11730 // receive HOVER_EXIT even though the mouse left the window.
11731 mDispatcher->notifyMotion(
11732 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11733 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11734 .rawXCursorPosition(150)
11735 .rawYCursorPosition(50)
11736 .deviceId(SECOND_DEVICE_ID)
11737 .build());
11738
11739 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11740 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11741 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11742 /*pointerId=*/0));
11743 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11744 SECOND_DEVICE_ID,
11745 /*pointerId=*/0));
11746}
11747
Garfield Tane84e6f92019-08-29 17:28:41 -070011748} // namespace android::inputdispatcher