blob: b6ae0b3d699de30a730019fc099b38c43008d2f2 [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
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800864 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
865 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700866 if (!consumeSeq) {
867 return nullptr;
868 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000869 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800870 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 }
872
873 /**
874 * Receive an event without acknowledging it.
875 * Return the sequence number that could later be used to send finished signal.
876 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800877 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
878 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800879 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800880 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800881
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800882 std::chrono::time_point start = std::chrono::steady_clock::now();
883 status_t status = WOULD_BLOCK;
884 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800885 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700886 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800887 &rawEventPtr);
888 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800889 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700890 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800891 break;
892 }
893 }
894
895 if (status == WOULD_BLOCK) {
896 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800897 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800898 }
899
900 if (status != OK) {
901 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800902 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800903 }
904 if (event == nullptr) {
905 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800906 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800907 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700908 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800909
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 /**
911 * To be used together with "receiveEvent" to complete the consumption of an event.
912 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000913 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700914 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700915 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800916 }
917
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000918 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700919 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000920 ASSERT_EQ(OK, status);
921 }
922
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700923 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000924 std::optional<int32_t> expectedDisplayId,
925 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800926 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800927
928 ASSERT_NE(nullptr, event) << mName.c_str()
929 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800930 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700931 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
932 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800933
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000934 if (expectedDisplayId.has_value()) {
935 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
936 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800937
Tiger Huang8664f8c2018-10-11 19:14:35 +0800938 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700939 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800940 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700941 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000942 if (expectedFlags.has_value()) {
943 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
944 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800945 break;
946 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700947 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800948 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700949 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000950 if (expectedFlags.has_value()) {
951 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
952 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800953 break;
954 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700955 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100956 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
957 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700958 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800959 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
960 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700961 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000962 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800965 FAIL() << "Use 'consumeDragEvent' for DRAG events";
966 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800967 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800968 }
969
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800970 std::unique_ptr<MotionEvent> consumeMotion() {
971 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800972
973 if (event == nullptr) {
974 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
975 return nullptr;
976 }
977
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700978 if (event->getType() != InputEventType::MOTION) {
979 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800980 return nullptr;
981 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800982 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800983 }
984
985 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800986 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800987 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
988 ASSERT_THAT(*motionEvent, matcher);
989 }
990
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100991 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800992 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100993 ASSERT_NE(nullptr, event) << mName.c_str()
994 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700995 ASSERT_EQ(InputEventType::FOCUS, event->getType())
996 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100997
998 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
999 << mName.c_str() << ": event displayId should always be NONE.";
1000
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001001 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1002 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001003 }
1004
Prabir Pradhan99987712020-11-10 18:43:05 -08001005 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001006 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001007 ASSERT_NE(nullptr, event) << mName.c_str()
1008 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001009 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1010 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001011
1012 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1013 << mName.c_str() << ": event displayId should always be NONE.";
1014
1015 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1016 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1017 }
1018
arthurhungb89ccb02020-12-30 16:19:01 +08001019 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001020 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001021 ASSERT_NE(nullptr, event) << mName.c_str()
1022 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001023 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001024
1025 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1026 << mName.c_str() << ": event displayId should always be NONE.";
1027
1028 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1029 EXPECT_EQ(isExiting, dragEvent.isExiting());
1030 EXPECT_EQ(x, dragEvent.getX());
1031 EXPECT_EQ(y, dragEvent.getY());
1032 }
1033
Antonio Kantekf16f2832021-09-28 04:39:20 +00001034 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001035 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001036 ASSERT_NE(nullptr, event) << mName.c_str()
1037 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001038 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1039 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001040
1041 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1042 << mName.c_str() << ": event displayId should always be NONE.";
1043 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1044 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1045 }
1046
chaviwd1c23182019-12-20 18:44:56 -08001047 void assertNoEvents() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001048 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001049 if (event == nullptr) {
1050 return;
1051 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001052 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001053 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001054 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001055 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001056 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001057 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001059 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1060 ADD_FAILURE() << "Received focus event, hasFocus = "
1061 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001062 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001063 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1064 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1065 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001066 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001067 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1068 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1069 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001070 }
1071 FAIL() << mName.c_str()
1072 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001073 }
1074
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001075 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001076
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001077 int getChannelFd() { return mConsumer.getChannel()->getFd().get(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001078
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001079private:
1080 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001081 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001082
1083 std::string mName;
1084};
1085
chaviw3277faf2021-05-19 16:45:23 -05001086class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001087public:
1088 static const int32_t WIDTH = 600;
1089 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001090
Chris Yea209fde2020-07-22 13:54:51 -07001091 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001092 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001093 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001094 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001095 sp<IBinder> token;
1096 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001097 base::Result<std::unique_ptr<InputChannel>> channel =
1098 dispatcher->createInputChannel(name);
1099 token = (*channel)->getConnectionToken();
1100 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001101 }
1102
1103 inputApplicationHandle->updateInfo();
1104 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1105
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001106 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001107 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001108 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001109 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001110 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001111 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001112 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001113 mInfo.globalScaleFactor = 1.0;
1114 mInfo.touchableRegion.clear();
1115 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001116 mInfo.ownerPid = WINDOW_PID;
1117 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001118 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001119 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001120 }
1121
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001122 sp<FakeWindowHandle> clone(int32_t displayId) {
1123 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1124 handle->mInfo = mInfo;
1125 handle->mInfo.displayId = displayId;
1126 handle->mInfo.id = sId++;
1127 handle->mInputReceiver = mInputReceiver;
1128 return handle;
1129 }
1130
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001131 void setTouchable(bool touchable) {
1132 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1133 }
chaviwd1c23182019-12-20 18:44:56 -08001134
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001135 void setFocusable(bool focusable) {
1136 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1137 }
1138
1139 void setVisible(bool visible) {
1140 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1141 }
Vishnu Nair958da932020-08-21 17:12:37 -07001142
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001143 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001144 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001145 }
1146
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001147 void setPaused(bool paused) {
1148 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1149 }
1150
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001151 void setPreventSplitting(bool preventSplitting) {
1152 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001153 }
1154
1155 void setSlippery(bool slippery) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1157 }
1158
1159 void setWatchOutsideTouch(bool watchOutside) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1161 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001162
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001163 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1164
1165 void setInterceptsStylus(bool interceptsStylus) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1167 }
1168
1169 void setDropInput(bool dropInput) {
1170 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1171 }
1172
1173 void setDropInputIfObscured(bool dropInputIfObscured) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1175 }
1176
1177 void setNoInputChannel(bool noInputChannel) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1179 }
1180
Josep del Riob3981622023-04-18 15:49:45 +00001181 void setDisableUserActivity(bool disableUserActivity) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1183 }
1184
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001185 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1187 shouldGlobalStylusBlockTouch);
1188 }
1189
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001190 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1191
chaviw3277faf2021-05-19 16:45:23 -05001192 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001193
Bernardo Rufino7393d172021-02-26 13:56:11 +00001194 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1195
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001196 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001197 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001198 mInfo.touchableRegion.clear();
1199 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001200
1201 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1202 ui::Transform translate;
1203 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1204 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001205 }
1206
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001207 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1208
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001209 void setIsWallpaper(bool isWallpaper) {
1210 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1211 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001212
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001213 void setDupTouchToWallpaper(bool hasWallpaper) {
1214 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1215 }
chaviwd1c23182019-12-20 18:44:56 -08001216
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001217 void setTrustedOverlay(bool trustedOverlay) {
1218 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1219 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001220
chaviw9eaa22c2020-07-01 16:21:27 -07001221 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1222 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1223 }
1224
1225 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001226
yunho.shinf4a80b82020-11-16 21:13:57 +09001227 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1228
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001229 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1230 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1231 if (event == nullptr) {
1232 ADD_FAILURE() << "No event";
1233 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001234 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001235 if (event->getType() != InputEventType::KEY) {
1236 ADD_FAILURE() << "Instead of key event, got " << event;
1237 return nullptr;
1238 }
1239 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001240 }
1241
1242 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001243 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1244 ASSERT_NE(nullptr, keyEvent);
1245 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001246 }
1247
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001248 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001249 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1250 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001251 }
1252
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001253 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001254 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1255 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001256 }
1257
Svet Ganov5d3bc372020-01-26 23:11:07 -08001258 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001259 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001260 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1261 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 }
1263
1264 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001265 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001266 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1267 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001268 }
1269
1270 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001271 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001272 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1273 }
1274
1275 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1276 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001277 consumeMotionEvent(
1278 AllOf(WithMotionAction(ACTION_DOWN),
1279 testing::Conditional(expectedDisplayId.has_value(),
1280 WithDisplayId(*expectedDisplayId), testing::_),
1281 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1282 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001283 }
1284
Svet Ganov5d3bc372020-01-26 23:11:07 -08001285 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001286 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1287 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001288 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001289 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001290 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1291 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001292 }
1293
1294 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001295 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001296 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001297 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001298 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1299 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001300 }
1301
1302 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001303 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001304 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1305 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001306 }
1307
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001308 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1309 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001310 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1311 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001312 }
1313
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001314 void consumeMotionOutsideWithZeroedCoords() {
1315 consumeMotionEvent(
1316 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001317 }
1318
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001319 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1320 ASSERT_NE(mInputReceiver, nullptr)
1321 << "Cannot consume events from a window with no receiver";
1322 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1323 }
1324
Prabir Pradhan99987712020-11-10 18:43:05 -08001325 void consumeCaptureEvent(bool hasCapture) {
1326 ASSERT_NE(mInputReceiver, nullptr)
1327 << "Cannot consume events from a window with no receiver";
1328 mInputReceiver->consumeCaptureEvent(hasCapture);
1329 }
1330
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001331 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001332 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001333 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1334 if (event == nullptr) {
1335 ADD_FAILURE() << "No event";
1336 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001337 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001338 if (event->getType() != InputEventType::MOTION) {
1339 ADD_FAILURE() << "Instead of motion event, got " << *event;
1340 return nullptr;
1341 }
1342 std::unique_ptr<MotionEvent> motionEvent =
1343 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1344 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001345 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001346 }
1347
arthurhungb89ccb02020-12-30 16:19:01 +08001348 void consumeDragEvent(bool isExiting, float x, float y) {
1349 mInputReceiver->consumeDragEvent(isExiting, x, y);
1350 }
1351
Antonio Kantekf16f2832021-09-28 04:39:20 +00001352 void consumeTouchModeEvent(bool inTouchMode) {
1353 ASSERT_NE(mInputReceiver, nullptr)
1354 << "Cannot consume events from a window with no receiver";
1355 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1356 }
1357
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001358 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001359 if (mInputReceiver == nullptr) {
1360 ADD_FAILURE() << "Invalid receive event on window with no receiver";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001361 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001362 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001363 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001364 }
1365
1366 void finishEvent(uint32_t sequenceNum) {
1367 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1368 mInputReceiver->finishEvent(sequenceNum);
1369 }
1370
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001371 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1372 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1373 mInputReceiver->sendTimeline(inputEventId, timeline);
1374 }
1375
Arthur Hungb92218b2018-08-14 12:00:21 +08001376 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001377 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001378 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001379 return; // Can't receive events if the window does not have input channel
1380 }
1381 ASSERT_NE(nullptr, mInputReceiver)
1382 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001383 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001384 }
1385
chaviwaf87b3e2019-10-01 16:59:28 -07001386 sp<IBinder> getToken() { return mInfo.token; }
1387
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001388 const std::string& getName() { return mName; }
1389
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001390 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001391 mInfo.ownerPid = ownerPid;
1392 mInfo.ownerUid = ownerUid;
1393 }
1394
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001395 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001396
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001397 void destroyReceiver() { mInputReceiver = nullptr; }
1398
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001399 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1400
chaviwd1c23182019-12-20 18:44:56 -08001401private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001402 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001403 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001404 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001405 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001406 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001407
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001408 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001409 if (mInputReceiver == nullptr) {
1410 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1411 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001412 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001413 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001414 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001415 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001416 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001417 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001418};
1419
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001420std::atomic<int32_t> FakeWindowHandle::sId{1};
1421
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001422class FakeMonitorReceiver {
1423public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001424 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1425 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001426
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001427 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001428
1429 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001430 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1431 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001432 }
1433
1434 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001435 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1436 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001437 }
1438
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001439 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001440
1441 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001442 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1443 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001444 }
1445
1446 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001447 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1448 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001449 }
1450
1451 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001452 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1453 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001454 }
1455
1456 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001457 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001458 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1459 WithDisplayId(expectedDisplayId),
1460 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1461 }
1462
1463 void consumeMotionPointerDown(int32_t pointerIdx) {
1464 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1465 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001466 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1467 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001468 }
1469
1470 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001471 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001472 }
1473
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001474 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001475
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001476 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001477
1478private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001479 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001480};
1481
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001482static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001483 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001484 int32_t displayId = ADISPLAY_ID_NONE,
1485 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001486 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001487 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001488 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001489 KeyEvent event;
1490 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1491
1492 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001493 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001494 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1495 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001496
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001497 if (!allowKeyRepeat) {
1498 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1499 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001500 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001501 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001502}
1503
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001504static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1505 InputEventInjectionResult result =
1506 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1507 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1508 if (result != InputEventInjectionResult::TIMED_OUT) {
1509 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1510 }
1511}
1512
1513static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001514 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001515 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001516}
1517
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001518// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1519// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1520// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001521static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1522 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001523 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001524 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001525 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001526}
1527
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001528static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001529 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001530 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001531}
1532
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001533static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001534 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001535 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001536 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001537 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001538 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1539 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001540}
1541
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001542static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001543 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1544 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001545 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001546 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1547 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001548 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001549 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001550 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001551 MotionEventBuilder motionBuilder =
1552 MotionEventBuilder(action, source)
1553 .displayId(displayId)
1554 .eventTime(eventTime)
1555 .rawXCursorPosition(cursorPosition.x)
1556 .rawYCursorPosition(cursorPosition.y)
1557 .pointer(
1558 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1559 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1560 motionBuilder.downTime(eventTime);
1561 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001562
1563 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001564 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1565 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001566}
1567
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001568static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1569 int32_t displayId,
1570 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001571 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001572}
1573
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001574static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1575 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001576 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001577 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001578}
1579
Jackal Guof9696682018-10-05 12:23:23 +08001580static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1581 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1582 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001583 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1584 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1585 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001586
1587 return args;
1588}
1589
Josep del Riob3981622023-04-18 15:49:45 +00001590static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1591 int32_t displayId = ADISPLAY_ID_NONE) {
1592 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1593 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001594 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1595 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1596 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001597
1598 return args;
1599}
1600
1601static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1602 int32_t displayId = ADISPLAY_ID_NONE) {
1603 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1604 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001605 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1606 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1607 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001608
1609 return args;
1610}
1611
Prabir Pradhan678438e2023-04-13 19:32:51 +00001612[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1613 int32_t displayId,
1614 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001615 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001616 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1617 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1618 }
1619
chaviwd1c23182019-12-20 18:44:56 -08001620 PointerProperties pointerProperties[pointerCount];
1621 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001622
chaviwd1c23182019-12-20 18:44:56 -08001623 for (size_t i = 0; i < pointerCount; i++) {
1624 pointerProperties[i].clear();
1625 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001626 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001627
chaviwd1c23182019-12-20 18:44:56 -08001628 pointerCoords[i].clear();
1629 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1630 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1631 }
Jackal Guof9696682018-10-05 12:23:23 +08001632
1633 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1634 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001635 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1636 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1637 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001638 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001639 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001640 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001641 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001642
1643 return args;
1644}
1645
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001646static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1647 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1648}
1649
chaviwd1c23182019-12-20 18:44:56 -08001650static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1651 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1652}
1653
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001654static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1655 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001656 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1657 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001658}
1659
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001660} // namespace
1661
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001662/**
1663 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1664 * broken channel.
1665 */
1666TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1668 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001669 sp<FakeWindowHandle>::make(application, mDispatcher,
1670 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001671
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001673
1674 // Window closes its channel, but the window remains.
1675 window->destroyReceiver();
1676 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1677}
1678
Arthur Hungb92218b2018-08-14 12:00:21 +08001679TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1682 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001683
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001687 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001688
1689 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001690 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001691}
1692
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001693using InputDispatcherDeathTest = InputDispatcherTest;
1694
1695/**
1696 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1697 * should crash.
1698 */
1699TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1700 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1701 ScopedSilentDeath _silentDeath;
1702
1703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1705 "Fake Window", ADISPLAY_ID_DEFAULT);
1706 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1707 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1708 "Incorrect WindowInfosUpdate provided");
1709}
1710
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001711TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1714 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001715
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001716 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001717 // Inject a MotionEvent to an unknown display.
1718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001719 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1721
1722 // Window should receive motion event.
1723 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1724}
1725
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001726/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001727 * Calling onWindowInfosChanged once should not cause any issues.
1728 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001729 * called twice.
1730 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001731TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1734 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001735 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001736
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001740 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001742
1743 // Window should receive motion event.
1744 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1745}
1746
1747/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001748 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001749 */
1750TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001752 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1753 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001754 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001755
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001756 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001759 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001760 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001762
1763 // Window should receive motion event.
1764 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1765}
1766
Arthur Hungb92218b2018-08-14 12:00:21 +08001767// The foreground window should receive the first touch down event.
1768TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001770 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001771 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001772 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001773 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001775 mDispatcher->onWindowInfosChanged(
1776 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001780
1781 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001782 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001783 windowSecond->assertNoEvents();
1784}
1785
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001786/**
1787 * Two windows: A top window, and a wallpaper behind the window.
1788 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1789 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001790 * 1. foregroundWindow <-- dup touch to wallpaper
1791 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001792 */
1793TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1795 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001796 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001797 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001798 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001799 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001800 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001801
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001802 mDispatcher->onWindowInfosChanged(
1803 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001805 injectMotionEvent(*mDispatcher,
1806 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1807 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1808 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1810
1811 // Both foreground window and its wallpaper should receive the touch down
1812 foregroundWindow->consumeMotionDown();
1813 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1814
1815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001816 injectMotionEvent(*mDispatcher,
1817 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1818 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1819 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1821
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001822 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001823 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1824
1825 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001826 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001827 foregroundWindow->consumeMotionCancel();
1828 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1829 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1830}
1831
1832/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001833 * Two fingers down on the window, and lift off the first finger.
1834 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1835 * contains a single pointer.
1836 */
1837TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1839 sp<FakeWindowHandle> window =
1840 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1841
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001843 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1845 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1846 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001847 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001848 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1849 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1850 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1851 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001852 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001853 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1854 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1855 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1856 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001857 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1858 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1859 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1860
1861 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001862 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001863 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1864 window->consumeMotionEvent(
1865 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1866}
1867
1868/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001869 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1870 * with the following differences:
1871 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1872 * clean up the connection.
1873 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1874 * Ensure that there's no crash in the dispatcher.
1875 */
1876TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1878 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001879 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001880 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001881 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001882 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001883 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001884
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001885 mDispatcher->onWindowInfosChanged(
1886 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001888 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001889 {100, 200}))
1890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1891
1892 // Both foreground window and its wallpaper should receive the touch down
1893 foregroundWindow->consumeMotionDown();
1894 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1895
1896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001897 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001898 ADISPLAY_ID_DEFAULT, {110, 200}))
1899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1900
1901 foregroundWindow->consumeMotionMove();
1902 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1903
1904 // Wallpaper closes its channel, but the window remains.
1905 wallpaperWindow->destroyReceiver();
1906 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1907
1908 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1909 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001910 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001911 foregroundWindow->consumeMotionCancel();
1912}
1913
Arthur Hungc539dbb2022-12-08 07:45:36 +00001914class ShouldSplitTouchFixture : public InputDispatcherTest,
1915 public ::testing::WithParamInterface<bool> {};
1916INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1917 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001918/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001919 * A single window that receives touch (on top), and a wallpaper window underneath it.
1920 * The top window gets a multitouch gesture.
1921 * Ensure that wallpaper gets the same gesture.
1922 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001923TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001925 sp<FakeWindowHandle> foregroundWindow =
1926 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1927 foregroundWindow->setDupTouchToWallpaper(true);
1928 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001929
1930 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001931 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001932 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001934 mDispatcher->onWindowInfosChanged(
1935 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936
1937 // Touch down on top window
1938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001939 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001940 {100, 100}))
1941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1942
1943 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001944 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001945 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1946
1947 // Second finger down on the top window
1948 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001949 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001951 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1952 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001953 .build();
1954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001955 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956 InputEventInjectionSync::WAIT_FOR_RESULT))
1957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1958
Harry Cutts33476232023-01-30 19:57:29 +00001959 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1960 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001961 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001962
1963 const MotionEvent secondFingerUpEvent =
1964 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1965 .displayId(ADISPLAY_ID_DEFAULT)
1966 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001967 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1968 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001969 .build();
1970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001971 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001972 InputEventInjectionSync::WAIT_FOR_RESULT))
1973 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1974 foregroundWindow->consumeMotionPointerUp(0);
1975 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1976
1977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001978 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001979 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1980 AINPUT_SOURCE_TOUCHSCREEN)
1981 .displayId(ADISPLAY_ID_DEFAULT)
1982 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001983 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001984 .x(100)
1985 .y(100))
1986 .build(),
1987 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1989 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1990 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991}
1992
1993/**
1994 * Two windows: a window on the left and window on the right.
1995 * A third window, wallpaper, is behind both windows, and spans both top windows.
1996 * The first touch down goes to the left window. A second pointer touches down on the right window.
1997 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1998 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1999 * ACTION_POINTER_DOWN(1).
2000 */
2001TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2002 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2003 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002004 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002005 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002006 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002007
2008 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002009 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002010 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002011 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002012
2013 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002014 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002016 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002017
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002018 mDispatcher->onWindowInfosChanged(
2019 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2020 {},
2021 0,
2022 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023
2024 // Touch down on left window
2025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002026 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 {100, 100}))
2028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2029
2030 // Both foreground window and its wallpaper should receive the touch down
2031 leftWindow->consumeMotionDown();
2032 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2033
2034 // Second finger down on the right window
2035 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002036 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002037 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002038 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2039 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040 .build();
2041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002042 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002043 InputEventInjectionSync::WAIT_FOR_RESULT))
2044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2045
2046 leftWindow->consumeMotionMove();
2047 // Since the touch is split, right window gets ACTION_DOWN
2048 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002049 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002050 expectedWallpaperFlags);
2051
2052 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002053 mDispatcher->onWindowInfosChanged(
2054 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002055 leftWindow->consumeMotionCancel();
2056 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2057 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2058
2059 // The pointer that's still down on the right window moves, and goes to the right window only.
2060 // As far as the dispatcher's concerned though, both pointers are still present.
2061 const MotionEvent secondFingerMoveEvent =
2062 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2063 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002064 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2065 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002066 .build();
2067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002068 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002069 InputEventInjectionSync::WAIT_FOR_RESULT));
2070 rightWindow->consumeMotionMove();
2071
2072 leftWindow->assertNoEvents();
2073 rightWindow->assertNoEvents();
2074 wallpaperWindow->assertNoEvents();
2075}
2076
Arthur Hungc539dbb2022-12-08 07:45:36 +00002077/**
2078 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2079 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2080 * The right window should receive ACTION_DOWN.
2081 */
2082TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002084 sp<FakeWindowHandle> leftWindow =
2085 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2086 leftWindow->setFrame(Rect(0, 0, 200, 200));
2087 leftWindow->setDupTouchToWallpaper(true);
2088 leftWindow->setSlippery(true);
2089
2090 sp<FakeWindowHandle> rightWindow =
2091 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2092 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002093
2094 sp<FakeWindowHandle> wallpaperWindow =
2095 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2096 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002097
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002098 mDispatcher->onWindowInfosChanged(
2099 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2100 {},
2101 0,
2102 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002103
Arthur Hungc539dbb2022-12-08 07:45:36 +00002104 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002106 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002107 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002109
2110 // Both foreground window and its wallpaper should receive the touch down
2111 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002112 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2113
Arthur Hungc539dbb2022-12-08 07:45:36 +00002114 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002116 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002117 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2119
Arthur Hungc539dbb2022-12-08 07:45:36 +00002120 leftWindow->consumeMotionCancel();
2121 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2122 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002123}
2124
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002125/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002126 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2127 * interactive, it might stop sending this flag.
2128 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2129 * to have a consistent input stream.
2130 *
2131 * Test procedure:
2132 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2133 * DOWN (new gesture).
2134 *
2135 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2136 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2137 *
2138 * We technically just need a single window here, but we are using two windows (spy on top and a
2139 * regular window below) to emulate the actual situation where it happens on the device.
2140 */
2141TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2142 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2143 sp<FakeWindowHandle> spyWindow =
2144 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2145 spyWindow->setFrame(Rect(0, 0, 200, 200));
2146 spyWindow->setTrustedOverlay(true);
2147 spyWindow->setSpy(true);
2148
2149 sp<FakeWindowHandle> window =
2150 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2151 window->setFrame(Rect(0, 0, 200, 200));
2152
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002153 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002154 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002155
2156 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002157 mDispatcher->notifyMotion(
2158 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2159 .deviceId(touchDeviceId)
2160 .policyFlags(DEFAULT_POLICY_FLAGS)
2161 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2162 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002163
Prabir Pradhan678438e2023-04-13 19:32:51 +00002164 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2165 .deviceId(touchDeviceId)
2166 .policyFlags(DEFAULT_POLICY_FLAGS)
2167 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2168 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2169 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002170 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2171 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2172 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2173 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2174
2175 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002176 mDispatcher->notifyMotion(
2177 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2178 .deviceId(touchDeviceId)
2179 .policyFlags(0)
2180 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2181 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2182 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002183 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2184 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2185
2186 // We don't need to reset the device to reproduce the issue, but the reset event typically
2187 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002188 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002189
2190 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002191 mDispatcher->notifyMotion(
2192 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2193 .deviceId(touchDeviceId)
2194 .policyFlags(DEFAULT_POLICY_FLAGS)
2195 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2196 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002197 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2198 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2199
2200 // No more events
2201 spyWindow->assertNoEvents();
2202 window->assertNoEvents();
2203}
2204
2205/**
Linnan Li907ae732023-09-05 17:14:21 +08002206 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2207 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2208 * interactive, it might stop sending this flag.
2209 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2210 * the consistency of the hover event in this case.
2211 *
2212 * Test procedure:
2213 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2214 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2215 *
2216 * We expect to receive two full streams of hover events.
2217 */
2218TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2220
2221 sp<FakeWindowHandle> window =
2222 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2223 window->setFrame(Rect(0, 0, 300, 300));
2224
2225 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2226
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2228 .policyFlags(DEFAULT_POLICY_FLAGS)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2230 .build());
2231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2232
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2234 .policyFlags(DEFAULT_POLICY_FLAGS)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2236 .build());
2237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2238
2239 // Send hover exit without the default policy flags.
2240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2241 .policyFlags(0)
2242 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2243 .build());
2244
2245 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2246
2247 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2248 // right event.
2249 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2250 .policyFlags(DEFAULT_POLICY_FLAGS)
2251 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2252 .build());
2253 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2254
2255 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2256 .policyFlags(DEFAULT_POLICY_FLAGS)
2257 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2258 .build());
2259 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2260
2261 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2262 .policyFlags(DEFAULT_POLICY_FLAGS)
2263 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2264 .build());
2265 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2266}
2267
2268/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002269 * Two windows: a window on the left and a window on the right.
2270 * Mouse is hovered from the right window into the left window.
2271 * Next, we tap on the left window, where the cursor was last seen.
2272 * The second tap is done onto the right window.
2273 * The mouse and tap are from two different devices.
2274 * We technically don't need to set the downtime / eventtime for these events, but setting these
2275 * explicitly helps during debugging.
2276 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2277 * In the buggy implementation, a tap on the right window would cause a crash.
2278 */
2279TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2281 sp<FakeWindowHandle> leftWindow =
2282 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2283 leftWindow->setFrame(Rect(0, 0, 200, 200));
2284
2285 sp<FakeWindowHandle> rightWindow =
2286 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2287 rightWindow->setFrame(Rect(200, 0, 400, 200));
2288
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002289 mDispatcher->onWindowInfosChanged(
2290 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002291 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2292 // stale.
2293 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2294 const int32_t mouseDeviceId = 6;
2295 const int32_t touchDeviceId = 4;
2296 // Move the cursor from right
2297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002298 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002299 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2300 AINPUT_SOURCE_MOUSE)
2301 .deviceId(mouseDeviceId)
2302 .downTime(baseTime + 10)
2303 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002304 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002305 .build()));
2306 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2307
2308 // .. to the left window
2309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002310 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002311 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2312 AINPUT_SOURCE_MOUSE)
2313 .deviceId(mouseDeviceId)
2314 .downTime(baseTime + 10)
2315 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002316 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002317 .build()));
2318 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2319 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2320 // Now tap the left window
2321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002322 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002323 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2324 AINPUT_SOURCE_TOUCHSCREEN)
2325 .deviceId(touchDeviceId)
2326 .downTime(baseTime + 40)
2327 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002328 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002329 .build()));
2330 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2331 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2332
2333 // release tap
2334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002335 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002336 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2337 AINPUT_SOURCE_TOUCHSCREEN)
2338 .deviceId(touchDeviceId)
2339 .downTime(baseTime + 40)
2340 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002341 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002342 .build()));
2343 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2344
2345 // Tap the window on the right
2346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002347 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002348 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2349 AINPUT_SOURCE_TOUCHSCREEN)
2350 .deviceId(touchDeviceId)
2351 .downTime(baseTime + 60)
2352 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002353 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002354 .build()));
2355 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2356
2357 // release tap
2358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002359 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002360 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2361 AINPUT_SOURCE_TOUCHSCREEN)
2362 .deviceId(touchDeviceId)
2363 .downTime(baseTime + 60)
2364 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002365 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002366 .build()));
2367 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2368
2369 // No more events
2370 leftWindow->assertNoEvents();
2371 rightWindow->assertNoEvents();
2372}
2373
2374/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002375 * Start hovering in a window. While this hover is still active, make another window appear on top.
2376 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2377 * While the top window is present, the hovering is stopped.
2378 * Later, hovering gets resumed again.
2379 * Ensure that new hover gesture is handled correctly.
2380 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2381 * to the window that's currently being hovered over.
2382 */
2383TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2385 sp<FakeWindowHandle> window =
2386 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2387 window->setFrame(Rect(0, 0, 200, 200));
2388
2389 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002390 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002391
2392 // Start hovering in the window
2393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2394 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2395 .build());
2396 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2397
2398 // Now, an obscuring window appears!
2399 sp<FakeWindowHandle> obscuringWindow =
2400 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2401 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002402 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002403 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2404 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2405 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2406 obscuringWindow->setNoInputChannel(true);
2407 obscuringWindow->setFocusable(false);
2408 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002409 mDispatcher->onWindowInfosChanged(
2410 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002411
2412 // While this new obscuring window is present, the hovering is stopped
2413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2414 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2415 .build());
2416 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2417
2418 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002419 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002420
2421 // And a new hover gesture starts.
2422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2424 .build());
2425 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2426}
2427
2428/**
2429 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2430 * the obscuring window.
2431 */
2432TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2434 sp<FakeWindowHandle> window =
2435 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2436 window->setFrame(Rect(0, 0, 200, 200));
2437
2438 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002440
2441 // Start hovering in the window
2442 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2443 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2444 .build());
2445 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2446
2447 // Now, an obscuring window appears!
2448 sp<FakeWindowHandle> obscuringWindow =
2449 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2450 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002451 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002452 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2453 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2454 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2455 obscuringWindow->setNoInputChannel(true);
2456 obscuringWindow->setFocusable(false);
2457 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002458 mDispatcher->onWindowInfosChanged(
2459 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002460
2461 // While this new obscuring window is present, the hovering continues. The event can't go to the
2462 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2464 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2465 .build());
2466 obscuringWindow->assertNoEvents();
2467 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2468
2469 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002470 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002471
2472 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2473 // so it should generate a HOVER_ENTER
2474 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2475 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2476 .build());
2477 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2478
2479 // Now the MOVE should be getting dispatched normally
2480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2482 .build());
2483 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2484}
2485
2486/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002487 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2488 * events are delivered to the window.
2489 */
2490TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2492 sp<FakeWindowHandle> window =
2493 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2494 window->setFrame(Rect(0, 0, 200, 200));
2495 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2496
2497 // Start hovering in the window
2498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2499 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2500 .build());
2501 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2502
2503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2504 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2505 .build());
2506 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2507
2508 // Scroll with the mouse
2509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2510 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2511 .build());
2512 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2513}
2514
2515using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2516
2517/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002518 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2519 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002520 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002521TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002522 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2523 sp<FakeWindowHandle> window =
2524 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2525 window->setFrame(Rect(0, 0, 200, 200));
2526
2527 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2528
2529 constexpr int32_t touchDeviceId = 4;
2530 constexpr int32_t stylusDeviceId = 2;
2531
2532 // Stylus down
2533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2534 .deviceId(stylusDeviceId)
2535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2536 .build());
2537 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2538
2539 // Touch down
2540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2541 .deviceId(touchDeviceId)
2542 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2543 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002544
2545 // Touch move
2546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2547 .deviceId(touchDeviceId)
2548 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2549 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002550 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002551
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002552 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2554 .deviceId(stylusDeviceId)
2555 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2556 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002557 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2558 WithCoords(101, 111)));
2559
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002560 window->assertNoEvents();
2561}
2562
2563/**
2564 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002565 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002566 * Similar test as above, but with added SPY window.
2567 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002568TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2570 sp<FakeWindowHandle> window =
2571 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2572 sp<FakeWindowHandle> spyWindow =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2574 spyWindow->setFrame(Rect(0, 0, 200, 200));
2575 spyWindow->setTrustedOverlay(true);
2576 spyWindow->setSpy(true);
2577 window->setFrame(Rect(0, 0, 200, 200));
2578
2579 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2580
2581 constexpr int32_t touchDeviceId = 4;
2582 constexpr int32_t stylusDeviceId = 2;
2583
2584 // Stylus down
2585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2586 .deviceId(stylusDeviceId)
2587 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2588 .build());
2589 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2590 spyWindow->consumeMotionEvent(
2591 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2592
2593 // Touch down
2594 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2595 .deviceId(touchDeviceId)
2596 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2597 .build());
2598
2599 // Touch move
2600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2601 .deviceId(touchDeviceId)
2602 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2603 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002604
2605 // Touch is ignored because stylus is already down
2606
2607 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2609 .deviceId(stylusDeviceId)
2610 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2611 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002612 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2613 WithCoords(101, 111)));
2614 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2615 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002616
2617 window->assertNoEvents();
2618 spyWindow->assertNoEvents();
2619}
2620
2621/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002622 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002623 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002624 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002625TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2627 sp<FakeWindowHandle> window =
2628 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2629 window->setFrame(Rect(0, 0, 200, 200));
2630
2631 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2632
2633 constexpr int32_t touchDeviceId = 4;
2634 constexpr int32_t stylusDeviceId = 2;
2635
2636 // Stylus down on the window
2637 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2638 .deviceId(stylusDeviceId)
2639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2640 .build());
2641 window->consumeMotionEvent(
2642 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2643
2644 // Touch down on window
2645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2646 .deviceId(touchDeviceId)
2647 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2648 .build());
2649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2650 .deviceId(touchDeviceId)
2651 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2652 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002653
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002654 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002655
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002656 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2658 .deviceId(stylusDeviceId)
2659 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2660 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002661 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2662 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002663
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002664 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2666 .deviceId(touchDeviceId)
2667 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2668 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002669 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002670}
2671
2672/**
2673 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002674 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002675 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002676TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2678 sp<FakeWindowHandle> window =
2679 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2680 window->setFrame(Rect(0, 0, 200, 200));
2681
2682 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2683
2684 constexpr int32_t touchDeviceId = 4;
2685 constexpr int32_t stylusDeviceId = 2;
2686
2687 // Touch down on window
2688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2689 .deviceId(touchDeviceId)
2690 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2691 .build());
2692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2693 .deviceId(touchDeviceId)
2694 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2695 .build());
2696 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2697 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2698
2699 // Stylus hover on the window
2700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2701 .deviceId(stylusDeviceId)
2702 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2703 .build());
2704 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2705 .deviceId(stylusDeviceId)
2706 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2707 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002708 // Stylus hover movement causes touch to be canceled
2709 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2710 WithCoords(141, 146)));
2711 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2712 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2713 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2714 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002715
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002716 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2718 .deviceId(touchDeviceId)
2719 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2720 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002721
2722 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002723}
2724
2725/**
2726 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2727 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2728 * become active.
2729 */
2730TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2732 sp<FakeWindowHandle> window =
2733 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2734 window->setFrame(Rect(0, 0, 200, 200));
2735
2736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2737
2738 constexpr int32_t stylusDeviceId1 = 3;
2739 constexpr int32_t stylusDeviceId2 = 5;
2740
2741 // Touch down on window
2742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2743 .deviceId(stylusDeviceId1)
2744 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2745 .build());
2746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2747 .deviceId(stylusDeviceId1)
2748 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2749 .build());
2750 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2751 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2752
2753 // Second stylus down
2754 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2755 .deviceId(stylusDeviceId2)
2756 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2757 .build());
2758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2759 .deviceId(stylusDeviceId2)
2760 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2761 .build());
2762
2763 // First stylus is canceled, second one takes over.
2764 window->consumeMotionEvent(
2765 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2766 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2767 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2768
2769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2770 .deviceId(stylusDeviceId1)
2771 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2772 .build());
2773 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002774 window->assertNoEvents();
2775}
2776
2777/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002778 * One window. Touch down on the window. Then, stylus down on the window from another device.
2779 * Ensure that is canceled, because stylus down should be preferred over touch.
2780 */
2781TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2782 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2783 sp<FakeWindowHandle> window =
2784 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2785 window->setFrame(Rect(0, 0, 200, 200));
2786
2787 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2788
2789 constexpr int32_t touchDeviceId = 4;
2790 constexpr int32_t stylusDeviceId = 2;
2791
2792 // Touch down on window
2793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2794 .deviceId(touchDeviceId)
2795 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2796 .build());
2797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2798 .deviceId(touchDeviceId)
2799 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2800 .build());
2801 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2802 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2803
2804 // Stylus down on the window
2805 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2806 .deviceId(stylusDeviceId)
2807 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2808 .build());
2809 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2810 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2811
2812 // Subsequent stylus movements are delivered correctly
2813 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2814 .deviceId(stylusDeviceId)
2815 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2816 .build());
2817 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2818 WithCoords(101, 111)));
2819}
2820
2821/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002822 * Two windows: a window on the left and a window on the right.
2823 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2824 * down. Then, on the left window, also place second touch pointer down.
2825 * This test tries to reproduce a crash.
2826 * In the buggy implementation, second pointer down on the left window would cause a crash.
2827 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002828TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2830 sp<FakeWindowHandle> leftWindow =
2831 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2832 leftWindow->setFrame(Rect(0, 0, 200, 200));
2833
2834 sp<FakeWindowHandle> rightWindow =
2835 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2836 rightWindow->setFrame(Rect(200, 0, 400, 200));
2837
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002838 mDispatcher->onWindowInfosChanged(
2839 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002840
2841 const int32_t touchDeviceId = 4;
2842 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002843
2844 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2846 .deviceId(mouseDeviceId)
2847 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2848 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002849 leftWindow->consumeMotionEvent(
2850 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2851
2852 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2854 .deviceId(mouseDeviceId)
2855 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2856 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2857 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858
2859 leftWindow->consumeMotionEvent(
2860 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2861 leftWindow->consumeMotionEvent(
2862 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2863
Prabir Pradhan678438e2023-04-13 19:32:51 +00002864 mDispatcher->notifyMotion(
2865 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2866 .deviceId(mouseDeviceId)
2867 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2868 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2869 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2870 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002871 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2872
2873 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2875 .deviceId(touchDeviceId)
2876 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2877 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002878 leftWindow->assertNoEvents();
2879
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002880 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2881
2882 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002883 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2884 .deviceId(touchDeviceId)
2885 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2886 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2887 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002888 // Since this is now a new splittable pointer going down on the left window, and it's coming
2889 // from a different device, the current gesture in the left window (pointer down) should first
2890 // be canceled.
2891 leftWindow->consumeMotionEvent(
2892 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002893 leftWindow->consumeMotionEvent(
2894 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2895 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2896 // current implementation.
2897 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2898 rightWindow->consumeMotionEvent(
2899 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2900
2901 leftWindow->assertNoEvents();
2902 rightWindow->assertNoEvents();
2903}
2904
2905/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002906 * Two windows: a window on the left and a window on the right.
2907 * Mouse is hovered on the left window and stylus is hovered on the right window.
2908 */
2909TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2910 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2911 sp<FakeWindowHandle> leftWindow =
2912 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2913 leftWindow->setFrame(Rect(0, 0, 200, 200));
2914
2915 sp<FakeWindowHandle> rightWindow =
2916 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2917 rightWindow->setFrame(Rect(200, 0, 400, 200));
2918
2919 mDispatcher->onWindowInfosChanged(
2920 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2921
2922 const int32_t stylusDeviceId = 3;
2923 const int32_t mouseDeviceId = 6;
2924
2925 // Start hovering over the left window
2926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2927 .deviceId(mouseDeviceId)
2928 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2929 .build());
2930 leftWindow->consumeMotionEvent(
2931 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2932
2933 // Stylus hovered on right window
2934 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2935 .deviceId(stylusDeviceId)
2936 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2937 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002938 rightWindow->consumeMotionEvent(
2939 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2940
2941 // Subsequent HOVER_MOVE events are dispatched correctly.
2942 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2943 .deviceId(mouseDeviceId)
2944 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2945 .build());
2946 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002947 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002948
2949 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2950 .deviceId(stylusDeviceId)
2951 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2952 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002953 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002954 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002955
2956 leftWindow->assertNoEvents();
2957 rightWindow->assertNoEvents();
2958}
2959
2960/**
2961 * Three windows: a window on the left and a window on the right.
2962 * And a spy window that's positioned above all of them.
2963 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2964 * Check the stream that's received by the spy.
2965 */
2966TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2968
2969 sp<FakeWindowHandle> spyWindow =
2970 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2971 spyWindow->setFrame(Rect(0, 0, 400, 400));
2972 spyWindow->setTrustedOverlay(true);
2973 spyWindow->setSpy(true);
2974
2975 sp<FakeWindowHandle> leftWindow =
2976 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2977 leftWindow->setFrame(Rect(0, 0, 200, 200));
2978
2979 sp<FakeWindowHandle> rightWindow =
2980 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2981
2982 rightWindow->setFrame(Rect(200, 0, 400, 200));
2983
2984 mDispatcher->onWindowInfosChanged(
2985 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2986
2987 const int32_t stylusDeviceId = 1;
2988 const int32_t touchDeviceId = 2;
2989
2990 // Stylus down on the left window
2991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2992 .deviceId(stylusDeviceId)
2993 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2994 .build());
2995 leftWindow->consumeMotionEvent(
2996 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2997 spyWindow->consumeMotionEvent(
2998 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2999
3000 // Touch down on the right window
3001 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3002 .deviceId(touchDeviceId)
3003 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3004 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003005 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003006 rightWindow->consumeMotionEvent(
3007 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003008
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003009 // Spy window does not receive touch events, because stylus events take precedence, and it
3010 // already has an active stylus gesture.
3011
3012 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3014 .deviceId(stylusDeviceId)
3015 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3016 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003017 leftWindow->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3019 spyWindow->consumeMotionEvent(
3020 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003021
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003022 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003023 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3024 .deviceId(touchDeviceId)
3025 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3026 .build());
3027 rightWindow->consumeMotionEvent(
3028 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003029
3030 spyWindow->assertNoEvents();
3031 leftWindow->assertNoEvents();
3032 rightWindow->assertNoEvents();
3033}
3034
3035/**
3036 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3037 * both.
3038 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003039 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003040 * At the same time, left and right should be getting independent streams of hovering and touch,
3041 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003042 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003043TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3045
3046 sp<FakeWindowHandle> spyWindow =
3047 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3048 spyWindow->setFrame(Rect(0, 0, 400, 400));
3049 spyWindow->setTrustedOverlay(true);
3050 spyWindow->setSpy(true);
3051
3052 sp<FakeWindowHandle> leftWindow =
3053 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3054 leftWindow->setFrame(Rect(0, 0, 200, 200));
3055
3056 sp<FakeWindowHandle> rightWindow =
3057 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3058 rightWindow->setFrame(Rect(200, 0, 400, 200));
3059
3060 mDispatcher->onWindowInfosChanged(
3061 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3062
3063 const int32_t stylusDeviceId = 1;
3064 const int32_t touchDeviceId = 2;
3065
3066 // Stylus hover on the left window
3067 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3068 .deviceId(stylusDeviceId)
3069 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3070 .build());
3071 leftWindow->consumeMotionEvent(
3072 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3073 spyWindow->consumeMotionEvent(
3074 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3075
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003076 // Touch down on the right window. Spy doesn't receive this touch because it already has
3077 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3079 .deviceId(touchDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3081 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003082 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003083 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003084 rightWindow->consumeMotionEvent(
3085 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3086
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003087 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3089 .deviceId(stylusDeviceId)
3090 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3091 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003092 leftWindow->consumeMotionEvent(
3093 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003094 spyWindow->consumeMotionEvent(
3095 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003096
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003097 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3099 .deviceId(touchDeviceId)
3100 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3101 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003102 rightWindow->consumeMotionEvent(
3103 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3104
3105 spyWindow->assertNoEvents();
3106 leftWindow->assertNoEvents();
3107 rightWindow->assertNoEvents();
3108}
3109
3110/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003111 * On a single window, use two different devices: mouse and touch.
3112 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3113 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3114 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3115 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3116 * represent a new gesture.
3117 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003118TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3120 sp<FakeWindowHandle> window =
3121 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3122 window->setFrame(Rect(0, 0, 400, 400));
3123
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003124 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003125
3126 const int32_t touchDeviceId = 4;
3127 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003128
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003129 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003130 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3131 .deviceId(touchDeviceId)
3132 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3133 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003134 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003135 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3136 .deviceId(touchDeviceId)
3137 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3138 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3139 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003141 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3142 .deviceId(touchDeviceId)
3143 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3144 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3145 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003146 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3147 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3148 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3149
3150 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003151 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3152 .deviceId(mouseDeviceId)
3153 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3154 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3155 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003156
3157 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003158 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003159 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3160
Prabir Pradhan678438e2023-04-13 19:32:51 +00003161 mDispatcher->notifyMotion(
3162 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3163 .deviceId(mouseDeviceId)
3164 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3165 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3166 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3167 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003168 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3169
3170 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003171 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3172 .deviceId(touchDeviceId)
3173 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3174 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3175 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003176 // Since we already canceled this touch gesture, it will be ignored until a completely new
3177 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3178 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3179 // However, mouse movements should continue to work.
3180 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3181 .deviceId(mouseDeviceId)
3182 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3183 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3184 .build());
3185 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3186
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003187 window->assertNoEvents();
3188}
3189
3190/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003191 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3192 * the injected event.
3193 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003194TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3196 sp<FakeWindowHandle> window =
3197 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3198 window->setFrame(Rect(0, 0, 400, 400));
3199
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003201
3202 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003203 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3204 // completion.
3205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003206 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003207 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3208 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003209 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003210 .build()));
3211 window->consumeMotionEvent(
3212 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3213
3214 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3215 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3217 .deviceId(touchDeviceId)
3218 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3219 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003220
3221 window->consumeMotionEvent(
3222 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3223 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3224}
3225
3226/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003227 * This test is similar to the test above, but the sequence of injected events is different.
3228 *
3229 * Two windows: a window on the left and a window on the right.
3230 * Mouse is hovered over the left window.
3231 * Next, we tap on the left window, where the cursor was last seen.
3232 *
3233 * After that, we inject one finger down onto the right window, and then a second finger down onto
3234 * the left window.
3235 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3236 * window (first), and then another on the left window (second).
3237 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3238 * In the buggy implementation, second finger down on the left window would cause a crash.
3239 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003240TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3242 sp<FakeWindowHandle> leftWindow =
3243 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3244 leftWindow->setFrame(Rect(0, 0, 200, 200));
3245
3246 sp<FakeWindowHandle> rightWindow =
3247 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3248 rightWindow->setFrame(Rect(200, 0, 400, 200));
3249
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003250 mDispatcher->onWindowInfosChanged(
3251 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003252
3253 const int32_t mouseDeviceId = 6;
3254 const int32_t touchDeviceId = 4;
3255 // Hover over the left window. Keep the cursor there.
3256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003257 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003258 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3259 AINPUT_SOURCE_MOUSE)
3260 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003261 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003262 .build()));
3263 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3264
3265 // Tap on left window
3266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003267 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3269 AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003271 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003272 .build()));
3273
3274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003275 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003276 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3277 AINPUT_SOURCE_TOUCHSCREEN)
3278 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003279 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003280 .build()));
3281 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3282 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3283 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3284
3285 // First finger down on right window
3286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003287 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003288 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3289 AINPUT_SOURCE_TOUCHSCREEN)
3290 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003291 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003292 .build()));
3293 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3294
3295 // Second finger down on the left window
3296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003297 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003298 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3299 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003300 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3301 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003302 .build()));
3303 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3304 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3305
3306 // No more events
3307 leftWindow->assertNoEvents();
3308 rightWindow->assertNoEvents();
3309}
3310
3311/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003312 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3313 * While the touch is down, new hover events from the stylus device should be ignored. After the
3314 * touch is gone, stylus hovering should start working again.
3315 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003316TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3318 sp<FakeWindowHandle> window =
3319 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3320 window->setFrame(Rect(0, 0, 200, 200));
3321
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003322 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003323
3324 const int32_t stylusDeviceId = 5;
3325 const int32_t touchDeviceId = 4;
3326 // Start hovering with stylus
3327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003328 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003329 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003330 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003332 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003333 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003334
3335 // Finger down on the window
3336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003338 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003339 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003340 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003341 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003342 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003343
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003344 // Continue hovering with stylus.
3345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003346 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003347 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3348 AINPUT_SOURCE_STYLUS)
3349 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003350 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003351 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003352 // Hovers continue to work
3353 window->consumeMotionEvent(
3354 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003355
3356 // Lift up the finger
3357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003358 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003359 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3360 AINPUT_SOURCE_TOUCHSCREEN)
3361 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003362 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003363 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003364
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003366 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003367 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3368 AINPUT_SOURCE_STYLUS)
3369 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003370 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003371 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003372 window->consumeMotionEvent(
3373 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003374 window->assertNoEvents();
3375}
3376
3377/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003378 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3379 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3380 *
3381 * Two windows: one on the left and one on the right.
3382 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3383 * Stylus down on the left window, and then touch down on the right window.
3384 * Check that the right window doesn't get touches while the stylus is down on the left window.
3385 */
3386TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3388 sp<FakeWindowHandle> leftWindow =
3389 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3390 ADISPLAY_ID_DEFAULT);
3391 leftWindow->setFrame(Rect(0, 0, 100, 100));
3392
3393 sp<FakeWindowHandle> sbtRightWindow =
3394 sp<FakeWindowHandle>::make(application, mDispatcher,
3395 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3396 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3397 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3398
3399 mDispatcher->onWindowInfosChanged(
3400 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3401
3402 const int32_t stylusDeviceId = 5;
3403 const int32_t touchDeviceId = 4;
3404
3405 // Stylus down in the left window
3406 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3407 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3408 .deviceId(stylusDeviceId)
3409 .build());
3410 leftWindow->consumeMotionEvent(
3411 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3412
3413 // Finger tap on the right window
3414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3415 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3416 .deviceId(touchDeviceId)
3417 .build());
3418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3419 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3420 .deviceId(touchDeviceId)
3421 .build());
3422
3423 // The touch should be blocked, because stylus is down somewhere else on screen!
3424 sbtRightWindow->assertNoEvents();
3425
3426 // Continue stylus motion, and ensure it's not impacted.
3427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3428 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3429 .deviceId(stylusDeviceId)
3430 .build());
3431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3432 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3433 .deviceId(stylusDeviceId)
3434 .build());
3435 leftWindow->consumeMotionEvent(
3436 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3437 leftWindow->consumeMotionEvent(
3438 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3439
3440 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3442 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3443 .deviceId(touchDeviceId)
3444 .build());
3445 sbtRightWindow->consumeMotionEvent(
3446 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3447}
3448
3449/**
3450 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3451 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3452 *
3453 * Two windows: one on the left and one on the right.
3454 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3455 * Stylus hover on the left window, and then touch down on the right window.
3456 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3457 */
3458TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3459 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3460 sp<FakeWindowHandle> leftWindow =
3461 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3462 ADISPLAY_ID_DEFAULT);
3463 leftWindow->setFrame(Rect(0, 0, 100, 100));
3464
3465 sp<FakeWindowHandle> sbtRightWindow =
3466 sp<FakeWindowHandle>::make(application, mDispatcher,
3467 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3468 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3469 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3470
3471 mDispatcher->onWindowInfosChanged(
3472 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3473
3474 const int32_t stylusDeviceId = 5;
3475 const int32_t touchDeviceId = 4;
3476
3477 // Stylus hover in the left window
3478 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3479 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3480 .deviceId(stylusDeviceId)
3481 .build());
3482 leftWindow->consumeMotionEvent(
3483 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3484
3485 // Finger tap on the right window
3486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3487 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3488 .deviceId(touchDeviceId)
3489 .build());
3490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3491 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3492 .deviceId(touchDeviceId)
3493 .build());
3494
3495 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3496 sbtRightWindow->assertNoEvents();
3497
3498 // Continue stylus motion, and ensure it's not impacted.
3499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3500 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3501 .deviceId(stylusDeviceId)
3502 .build());
3503 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3504 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3505 .deviceId(stylusDeviceId)
3506 .build());
3507 leftWindow->consumeMotionEvent(
3508 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3509 leftWindow->consumeMotionEvent(
3510 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3511
3512 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3514 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3515 .deviceId(touchDeviceId)
3516 .build());
3517 sbtRightWindow->consumeMotionEvent(
3518 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3519}
3520
3521/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003522 * A spy window above a window with no input channel.
3523 * Start hovering with a stylus device, and then tap with it.
3524 * Ensure spy window receives the entire sequence.
3525 */
3526TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3528 sp<FakeWindowHandle> spyWindow =
3529 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3530 spyWindow->setFrame(Rect(0, 0, 200, 200));
3531 spyWindow->setTrustedOverlay(true);
3532 spyWindow->setSpy(true);
3533 sp<FakeWindowHandle> window =
3534 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3535 window->setNoInputChannel(true);
3536 window->setFrame(Rect(0, 0, 200, 200));
3537
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003538 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003539
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003540 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, 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_ENTER));
3545 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3547 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3548 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003549 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3550
3551 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3553 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3554 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003555 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3556
3557 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3560 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003561 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3562
3563 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3566 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003567 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3568 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3570 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3571 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003572 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3573
3574 // No more events
3575 spyWindow->assertNoEvents();
3576 window->assertNoEvents();
3577}
3578
3579/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003580 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3581 * rejected. But since we already have an ongoing gesture, this event should be processed.
3582 * This prevents inconsistent events being handled inside the dispatcher.
3583 */
3584TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3585 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3586
3587 sp<FakeWindowHandle> window =
3588 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3589 window->setFrame(Rect(0, 0, 200, 200));
3590
3591 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3592
3593 // Start hovering with stylus
3594 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3595 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3596 .build());
3597 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3598
3599 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3600 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3601 .build();
3602 // Make this 'hoverExit' event stale
3603 mFakePolicy->setStaleEventTimeout(100ms);
3604 std::this_thread::sleep_for(100ms);
3605
3606 // It shouldn't be dropped by the dispatcher, even though it's stale.
3607 mDispatcher->notifyMotion(hoverExit);
3608 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3609
3610 // Stylus starts hovering again! There should be no crash.
3611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3612 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3613 .build());
3614 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3615}
3616
3617/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003618 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3619 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3620 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3621 * While the mouse is down, new move events from the touch device should be ignored.
3622 */
3623TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3625 sp<FakeWindowHandle> spyWindow =
3626 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3627 spyWindow->setFrame(Rect(0, 0, 200, 200));
3628 spyWindow->setTrustedOverlay(true);
3629 spyWindow->setSpy(true);
3630 sp<FakeWindowHandle> window =
3631 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3632 window->setFrame(Rect(0, 0, 200, 200));
3633
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003634 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635
3636 const int32_t mouseDeviceId = 7;
3637 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003638
3639 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3641 .deviceId(mouseDeviceId)
3642 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3643 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003644 spyWindow->consumeMotionEvent(
3645 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3646 window->consumeMotionEvent(
3647 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3648
3649 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3651 .deviceId(touchDeviceId)
3652 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003654 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3655 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3656 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3657 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3658
Prabir Pradhan678438e2023-04-13 19:32:51 +00003659 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3660 .deviceId(touchDeviceId)
3661 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3662 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003663 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3664 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3665
3666 // Pilfer the stream
3667 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3668 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3669
Prabir Pradhan678438e2023-04-13 19:32:51 +00003670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3671 .deviceId(touchDeviceId)
3672 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3673 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003674 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3675
3676 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003677 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3678 .deviceId(mouseDeviceId)
3679 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3680 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3681 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003682
3683 spyWindow->consumeMotionEvent(
3684 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3685 spyWindow->consumeMotionEvent(
3686 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3687 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3688
Prabir Pradhan678438e2023-04-13 19:32:51 +00003689 mDispatcher->notifyMotion(
3690 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3691 .deviceId(mouseDeviceId)
3692 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3693 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3694 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3695 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003696 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3697 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3698
3699 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3701 .deviceId(mouseDeviceId)
3702 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3703 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3704 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003705 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3706 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3707
3708 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003709 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3710 .deviceId(touchDeviceId)
3711 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3712 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003713
3714 // No more events
3715 spyWindow->assertNoEvents();
3716 window->assertNoEvents();
3717}
3718
3719/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003720 * On the display, have a single window, and also an area where there's no window.
3721 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3722 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3723 */
3724TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3725 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3726 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003727 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003728
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003730
3731 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003732 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003733
3734 mDispatcher->waitForIdle();
3735 window->assertNoEvents();
3736
3737 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003739 mDispatcher->waitForIdle();
3740 window->consumeMotionDown();
3741}
3742
3743/**
3744 * Same test as above, but instead of touching the empty space, the first touch goes to
3745 * non-touchable window.
3746 */
3747TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3749 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003750 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003751 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3752 window1->setTouchable(false);
3753 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003754 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003755 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003757 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003758
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003759 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003761
3762 mDispatcher->waitForIdle();
3763 window1->assertNoEvents();
3764 window2->assertNoEvents();
3765
3766 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003767 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003768 mDispatcher->waitForIdle();
3769 window2->consumeMotionDown();
3770}
3771
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003772/**
3773 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3774 * to the event time of the first ACTION_DOWN sent to the particular window.
3775 */
3776TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3778 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003779 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003780 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3781 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003782 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003783 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003785 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003786
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003787 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003788 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003789
3790 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003791
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003792 std::unique_ptr<MotionEvent> motionEvent1 = window1->consumeMotionEvent();
3793 ASSERT_NE(nullptr, motionEvent1);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003794 window2->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003795 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3796 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003797
3798 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003799 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003800 mDispatcher->waitForIdle();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003801 std::unique_ptr<MotionEvent> motionEvent2 = window2->consumeMotionEvent();
3802 ASSERT_NE(nullptr, motionEvent2);
3803 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003804 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003805 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003806
3807 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003808 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003809 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003810 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003811
3812 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003813 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003814 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003815 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003816
3817 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3818 window1->consumeMotionMove();
3819 window1->assertNoEvents();
3820
3821 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003822 mDispatcher->notifyMotion(
3823 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003824 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003825 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003826
Prabir Pradhan678438e2023-04-13 19:32:51 +00003827 mDispatcher->notifyMotion(
3828 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003829 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003830 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003831}
3832
Garfield Tandf26e862020-07-01 20:18:19 -07003833TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003835 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003836 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003837 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003838 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003839 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003840 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003841
3842 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3843
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003844 mDispatcher->onWindowInfosChanged(
3845 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003846
3847 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003849 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003850 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3851 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003853 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003854 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003855
3856 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003858 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003859 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3860 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003861 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003862 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003863 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3864 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003865
3866 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003868 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003869 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3870 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003871 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003872 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003873 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3874 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003875
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003877 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003878 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3879 AINPUT_SOURCE_MOUSE)
3880 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3881 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003882 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003883 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003884 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003885
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003887 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003888 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3889 AINPUT_SOURCE_MOUSE)
3890 .buttonState(0)
3891 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003892 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003893 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003894 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003895
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003897 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003898 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3899 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003901 .build()));
3902 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3903
3904 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003906 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003907 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3908 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003909 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003910 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003911 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003912
3913 // No more events
3914 windowLeft->assertNoEvents();
3915 windowRight->assertNoEvents();
3916}
3917
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003918/**
3919 * Put two fingers down (and don't release them) and click the mouse button.
3920 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3921 * currently active gesture should be canceled, and the new one should proceed.
3922 */
3923TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3925 sp<FakeWindowHandle> window =
3926 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3927 window->setFrame(Rect(0, 0, 600, 800));
3928
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003929 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003930
3931 const int32_t touchDeviceId = 4;
3932 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003933
3934 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3936 .deviceId(touchDeviceId)
3937 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3938 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003939
Prabir Pradhan678438e2023-04-13 19:32:51 +00003940 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3941 .deviceId(touchDeviceId)
3942 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3943 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3944 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003945 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3946 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3947
3948 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003949 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3950 .deviceId(mouseDeviceId)
3951 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3952 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3953 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003954 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3955 WithPointerCount(2u)));
3956 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3957
Prabir Pradhan678438e2023-04-13 19:32:51 +00003958 mDispatcher->notifyMotion(
3959 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3960 .deviceId(mouseDeviceId)
3961 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3962 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3963 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3964 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003965 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3966
3967 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3968 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3970 .deviceId(touchDeviceId)
3971 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3972 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3973 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003974 window->assertNoEvents();
3975}
3976
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003977TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3979
3980 sp<FakeWindowHandle> spyWindow =
3981 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3982 spyWindow->setFrame(Rect(0, 0, 600, 800));
3983 spyWindow->setTrustedOverlay(true);
3984 spyWindow->setSpy(true);
3985 sp<FakeWindowHandle> window =
3986 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3987 window->setFrame(Rect(0, 0, 600, 800));
3988
3989 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003990 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003991
3992 // Send mouse cursor to the window
3993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003994 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003995 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3996 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003997 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003998 .build()));
3999
4000 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4001 WithSource(AINPUT_SOURCE_MOUSE)));
4002 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4003 WithSource(AINPUT_SOURCE_MOUSE)));
4004
4005 window->assertNoEvents();
4006 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004007}
4008
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004009TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4011
4012 sp<FakeWindowHandle> spyWindow =
4013 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4014 spyWindow->setFrame(Rect(0, 0, 600, 800));
4015 spyWindow->setTrustedOverlay(true);
4016 spyWindow->setSpy(true);
4017 sp<FakeWindowHandle> window =
4018 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4019 window->setFrame(Rect(0, 0, 600, 800));
4020
4021 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004022 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004023
4024 // Send mouse cursor to the window
4025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004026 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004027 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4028 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004029 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004030 .build()));
4031
4032 // Move mouse cursor
4033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004034 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004035 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4036 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004037 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004038 .build()));
4039
4040 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4041 WithSource(AINPUT_SOURCE_MOUSE)));
4042 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4043 WithSource(AINPUT_SOURCE_MOUSE)));
4044 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4045 WithSource(AINPUT_SOURCE_MOUSE)));
4046 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4047 WithSource(AINPUT_SOURCE_MOUSE)));
4048 // Touch down on the window
4049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004050 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004051 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4052 AINPUT_SOURCE_TOUCHSCREEN)
4053 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004054 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004055 .build()));
4056 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4057 WithSource(AINPUT_SOURCE_MOUSE)));
4058 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4059 WithSource(AINPUT_SOURCE_MOUSE)));
4060 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4061 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4062 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4063 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4064
4065 // pilfer the motion, retaining the gesture on the spy window.
4066 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4067 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4068 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4069
4070 // Touch UP on the window
4071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004072 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004073 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4074 AINPUT_SOURCE_TOUCHSCREEN)
4075 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004076 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004077 .build()));
4078 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4079 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4080
4081 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4082 // to send a new gesture. It should again go to both windows (spy and the window below), just
4083 // like the first gesture did, before pilfering. The window configuration has not changed.
4084
4085 // One more tap - DOWN
4086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004087 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004088 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4089 AINPUT_SOURCE_TOUCHSCREEN)
4090 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004091 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004092 .build()));
4093 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4094 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4095 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4096 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4097
4098 // Touch UP on the window
4099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004100 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004101 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4102 AINPUT_SOURCE_TOUCHSCREEN)
4103 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004104 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004105 .build()));
4106 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4107 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4108 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4109 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4110
4111 window->assertNoEvents();
4112 spyWindow->assertNoEvents();
4113}
4114
Garfield Tandf26e862020-07-01 20:18:19 -07004115// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4116// directly in this test.
4117TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004119 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004120 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004121 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004122
4123 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4124
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004125 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004126
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004128 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004129 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4130 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004131 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004132 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004133 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004134 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004136 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004137 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4138 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004139 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004140 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004141 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4142 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004143
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004145 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004146 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4147 AINPUT_SOURCE_MOUSE)
4148 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4149 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004150 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004151 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004152 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004153
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004155 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004156 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4157 AINPUT_SOURCE_MOUSE)
4158 .buttonState(0)
4159 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004160 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004161 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004162 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004163
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004166 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4167 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004168 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004169 .build()));
4170 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4171
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004172 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4173 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4174 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004175 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004176 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4177 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004178 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004179 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004180 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004181}
4182
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004183/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004184 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4185 * is generated.
4186 */
4187TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4189 sp<FakeWindowHandle> window =
4190 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4191 window->setFrame(Rect(0, 0, 1200, 800));
4192
4193 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4194
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004195 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004196
4197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004198 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004199 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4200 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004201 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004202 .build()));
4203 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4204
4205 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004206 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004207 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4208}
4209
4210/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004211 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4212 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004213TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4214 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4215 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004216 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4217 sp<FakeWindowHandle> window =
4218 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4219 window->setFrame(Rect(0, 0, 1200, 800));
4220
4221 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4222
4223 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4224
4225 MotionEventBuilder hoverEnterBuilder =
4226 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4227 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4228 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4230 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4232 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4233 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4234 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4235}
4236
4237/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004238 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4239 */
4240TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4242 sp<FakeWindowHandle> window =
4243 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4244 window->setFrame(Rect(0, 0, 100, 100));
4245
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004246 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004247
4248 const int32_t mouseDeviceId = 7;
4249 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004250
4251 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004252 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4253 .deviceId(mouseDeviceId)
4254 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4255 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004256 window->consumeMotionEvent(
4257 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4258
4259 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4261 .deviceId(touchDeviceId)
4262 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4263 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004264
4265 window->consumeMotionEvent(
4266 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4267 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4268}
4269
4270/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004271 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004272 * The tap causes a HOVER_EXIT event to be generated because the current event
4273 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004274 */
4275TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4277 sp<FakeWindowHandle> window =
4278 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4279 window->setFrame(Rect(0, 0, 100, 100));
4280
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004281 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004282 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4283 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4284 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004285 ASSERT_NO_FATAL_FAILURE(
4286 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4287 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004288
4289 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004290 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4291 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4292 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004293 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004294 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4295 WithSource(AINPUT_SOURCE_MOUSE))));
4296
4297 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004298 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4299 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4300
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004301 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4302 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4303 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004304 ASSERT_NO_FATAL_FAILURE(
4305 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4306 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4307}
4308
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004309TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4310 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4311 sp<FakeWindowHandle> windowDefaultDisplay =
4312 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4313 ADISPLAY_ID_DEFAULT);
4314 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4315 sp<FakeWindowHandle> windowSecondDisplay =
4316 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4317 SECOND_DISPLAY_ID);
4318 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4319
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004320 mDispatcher->onWindowInfosChanged(
4321 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004322
4323 // Set cursor position in window in default display and check that hover enter and move
4324 // events are generated.
4325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004326 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004327 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4328 AINPUT_SOURCE_MOUSE)
4329 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004330 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004331 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004332 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004333
4334 // Remove all windows in secondary display and check that no event happens on window in
4335 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004336 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4337
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004338 windowDefaultDisplay->assertNoEvents();
4339
4340 // Move cursor position in window in default display and check that only hover move
4341 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004342 mDispatcher->onWindowInfosChanged(
4343 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004345 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004346 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4347 AINPUT_SOURCE_MOUSE)
4348 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004349 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004350 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004351 windowDefaultDisplay->consumeMotionEvent(
4352 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4353 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004354 windowDefaultDisplay->assertNoEvents();
4355}
4356
Garfield Tan00f511d2019-06-12 16:55:40 -07004357TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004359
4360 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004361 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004362 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004363 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004364 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004365 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004366
4367 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4368
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004369 mDispatcher->onWindowInfosChanged(
4370 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004371
4372 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4373 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004375 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004376 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004377 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004378 windowRight->assertNoEvents();
4379}
4380
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004381TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004383 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4384 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004385 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004386
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004387 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004388 setFocusedWindow(window);
4389
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004390 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004391
Prabir Pradhan678438e2023-04-13 19:32:51 +00004392 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004393
4394 // Window should receive key down event.
4395 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4396
4397 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4398 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004399 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004400 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004401}
4402
4403TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004405 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4406 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004407
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004408 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004409
Prabir Pradhan678438e2023-04-13 19:32:51 +00004410 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4411 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004412
4413 // Window should receive motion down event.
4414 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4415
4416 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4417 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004418 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004419 window->consumeMotionEvent(
4420 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004421}
4422
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004423TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4425 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4426 "Fake Window", ADISPLAY_ID_DEFAULT);
4427
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004428 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004429
4430 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4431 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4432 .build());
4433
4434 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4435
4436 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4437 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4438 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4439
4440 // After the device has been reset, a new hovering stream can be sent to the window
4441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4442 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4443 .build());
4444 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4445}
4446
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004447TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004449 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4450 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004451 window->setFocusable(true);
4452
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004453 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004454 setFocusedWindow(window);
4455
4456 window->consumeFocusEvent(true);
4457
Prabir Pradhan678438e2023-04-13 19:32:51 +00004458 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004459 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4460 const nsecs_t injectTime = keyArgs.eventTime;
4461 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004462 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004463 // The dispatching time should be always greater than or equal to intercept key timeout.
4464 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4465 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4466 std::chrono::nanoseconds(interceptKeyTimeout).count());
4467}
4468
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004469/**
4470 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4471 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004472TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004474 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4475 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004476 window->setFocusable(true);
4477
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004478 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004479 setFocusedWindow(window);
4480
4481 window->consumeFocusEvent(true);
4482
Prabir Pradhan678438e2023-04-13 19:32:51 +00004483 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004484 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004485
4486 // Set a value that's significantly larger than the default consumption timeout. If the
4487 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4488 mFakePolicy->setInterceptKeyTimeout(600ms);
4489 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4490 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004491 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4492}
4493
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004494/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004495 * Two windows. First is a regular window. Second does not overlap with the first, and has
4496 * WATCH_OUTSIDE_TOUCH.
4497 * Both windows are owned by the same UID.
4498 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4499 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4500 */
4501TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4502 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004503 sp<FakeWindowHandle> window =
4504 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004505 window->setFrame(Rect{0, 0, 100, 100});
4506
4507 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004508 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004509 ADISPLAY_ID_DEFAULT);
4510 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4511 outsideWindow->setWatchOutsideTouch(true);
4512 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004513 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004514
4515 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004516 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4517 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4518 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004519 window->consumeMotionDown();
4520 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4521 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4522 outsideWindow->consumeMotionEvent(
4523 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004524
4525 // Ensure outsideWindow doesn't get any more events for the gesture.
4526 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4527 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4528 window->consumeMotionMove();
4529 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004530}
4531
4532/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004533 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4534 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4535 * ACTION_OUTSIDE event is sent per gesture.
4536 */
4537TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4538 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004540 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4541 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004542 window->setWatchOutsideTouch(true);
4543 window->setFrame(Rect{0, 0, 100, 100});
4544 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004545 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4546 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004547 secondWindow->setFrame(Rect{100, 100, 200, 200});
4548 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004549 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4550 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004551 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004552 mDispatcher->onWindowInfosChanged(
4553 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004554
4555 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4557 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4558 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004559 window->assertNoEvents();
4560 secondWindow->assertNoEvents();
4561
4562 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4563 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004564 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4565 ADISPLAY_ID_DEFAULT,
4566 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004567 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4568 window->consumeMotionEvent(
4569 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004570 secondWindow->consumeMotionDown();
4571 thirdWindow->assertNoEvents();
4572
4573 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4574 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004575 mDispatcher->notifyMotion(
4576 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4577 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004578 window->assertNoEvents();
4579 secondWindow->consumeMotionMove();
4580 thirdWindow->consumeMotionDown();
4581}
4582
Prabir Pradhan814fe082022-07-22 20:22:18 +00004583TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004585 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4586 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004587 window->setFocusable(true);
4588
Patrick Williamsd828f302023-04-28 17:52:08 -05004589 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004590 setFocusedWindow(window);
4591
4592 window->consumeFocusEvent(true);
4593
Prabir Pradhan678438e2023-04-13 19:32:51 +00004594 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4595 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4596 mDispatcher->notifyKey(keyDown);
4597 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004598
4599 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4600 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4601
4602 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004603 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004604
4605 window->consumeFocusEvent(false);
4606
Prabir Pradhan678438e2023-04-13 19:32:51 +00004607 mDispatcher->notifyKey(keyDown);
4608 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004609 window->assertNoEvents();
4610}
4611
Arthur Hung96483742022-11-15 03:30:48 +00004612TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4613 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4614 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4615 "Fake Window", ADISPLAY_ID_DEFAULT);
4616 // Ensure window is non-split and have some transform.
4617 window->setPreventSplitting(true);
4618 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004619 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004620
4621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004622 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004623 {50, 50}))
4624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4625 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4626
4627 const MotionEvent secondFingerDownEvent =
4628 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4629 .displayId(ADISPLAY_ID_DEFAULT)
4630 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004631 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4632 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004633 .build();
4634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004635 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004636 InputEventInjectionSync::WAIT_FOR_RESULT))
4637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4638
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004639 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4640 ASSERT_NE(nullptr, event);
4641 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4642 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4643 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4644 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4645 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004646}
4647
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004648/**
4649 * Two windows: a splittable and a non-splittable.
4650 * The non-splittable window shouldn't receive any "incomplete" gestures.
4651 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4652 * The second pointer should be dropped because the initial window is splittable, so it won't get
4653 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4654 * "incomplete" gestures.
4655 */
4656TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4658 sp<FakeWindowHandle> leftWindow =
4659 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4660 ADISPLAY_ID_DEFAULT);
4661 leftWindow->setPreventSplitting(false);
4662 leftWindow->setFrame(Rect(0, 0, 100, 100));
4663 sp<FakeWindowHandle> rightWindow =
4664 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4665 ADISPLAY_ID_DEFAULT);
4666 rightWindow->setPreventSplitting(true);
4667 rightWindow->setFrame(Rect(100, 100, 200, 200));
4668 mDispatcher->onWindowInfosChanged(
4669 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4670
4671 // Touch down on left, splittable window
4672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4673 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4674 .build());
4675 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4676
4677 mDispatcher->notifyMotion(
4678 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4679 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4680 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4681 .build());
4682 leftWindow->assertNoEvents();
4683 rightWindow->assertNoEvents();
4684}
4685
Harry Cuttsb166c002023-05-09 13:06:05 +00004686TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4688 sp<FakeWindowHandle> window =
4689 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4690 window->setFrame(Rect(0, 0, 400, 400));
4691 sp<FakeWindowHandle> trustedOverlay =
4692 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4693 ADISPLAY_ID_DEFAULT);
4694 trustedOverlay->setSpy(true);
4695 trustedOverlay->setTrustedOverlay(true);
4696
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004697 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004698
4699 // Start a three-finger touchpad swipe
4700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4701 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4702 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4703 .build());
4704 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4705 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4706 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4707 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4708 .build());
4709 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4710 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4711 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4712 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4713 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4714 .build());
4715
4716 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4717 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4718 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4719
4720 // Move the swipe a bit
4721 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4722 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4723 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4724 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4725 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4726 .build());
4727
4728 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4729
4730 // End the swipe
4731 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4732 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4733 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4734 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4735 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4736 .build());
4737 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4738 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4739 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4740 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4741 .build());
4742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4743 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4744 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4745 .build());
4746
4747 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4748 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4749 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4750
4751 window->assertNoEvents();
4752}
4753
4754TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4756 sp<FakeWindowHandle> window =
4757 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4758 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004760
4761 // Start a three-finger touchpad swipe
4762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4764 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4765 .build());
4766 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4767 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4768 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4769 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4770 .build());
4771 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4772 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4773 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4774 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4775 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4776 .build());
4777
4778 // Move the swipe a bit
4779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4780 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4781 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4782 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4783 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4784 .build());
4785
4786 // End the swipe
4787 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4788 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4789 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4790 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4791 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4792 .build());
4793 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4794 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4795 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4796 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4797 .build());
4798 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4799 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4800 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4801 .build());
4802
4803 window->assertNoEvents();
4804}
4805
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004806/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004807 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4808 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004809 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004810 */
4811TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4813 sp<FakeWindowHandle> window =
4814 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4815 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004816 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004817
4818 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4819 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4820 .downTime(baseTime + 10)
4821 .eventTime(baseTime + 10)
4822 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4823 .build());
4824
4825 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4826
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004827 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004828 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004829
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004830 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004831
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004832 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4833 .downTime(baseTime + 10)
4834 .eventTime(baseTime + 30)
4835 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4836 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4837 .build());
4838
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004839 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4840
4841 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004842 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4843 .downTime(baseTime + 10)
4844 .eventTime(baseTime + 40)
4845 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4846 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4847 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004848
4849 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4850
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4852 .downTime(baseTime + 10)
4853 .eventTime(baseTime + 50)
4854 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4855 .build());
4856
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004857 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4858
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4860 .downTime(baseTime + 60)
4861 .eventTime(baseTime + 60)
4862 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4863 .build());
4864
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004865 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004866}
4867
4868/**
Hu Guo771a7692023-09-17 20:51:08 +08004869 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4870 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4871 * its coordinates should be converted by the transform of the windows of target screen.
4872 */
4873TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4874 // This case will create a window and a spy window on the default display and mirror
4875 // window on the second display. cancel event is sent through spy window pilferPointers
4876 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4877
4878 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4879 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4880 spyWindowDefaultDisplay->setTrustedOverlay(true);
4881 spyWindowDefaultDisplay->setSpy(true);
4882
4883 sp<FakeWindowHandle> windowDefaultDisplay =
4884 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4885 ADISPLAY_ID_DEFAULT);
4886 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4887
4888 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4889 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4890
4891 // Add the windows to the dispatcher
4892 mDispatcher->onWindowInfosChanged(
4893 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4894 *windowSecondDisplay->getInfo()},
4895 {},
4896 0,
4897 0});
4898
4899 // Send down to ADISPLAY_ID_DEFAULT
4900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4901 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4902 {100, 100}))
4903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4904
4905 spyWindowDefaultDisplay->consumeMotionDown();
4906 windowDefaultDisplay->consumeMotionDown();
4907
4908 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4909
4910 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004911 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4912 ASSERT_NE(nullptr, event);
4913 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004914
4915 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4916 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4917 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4918 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004919 EXPECT_EQ(100, event->getX(0));
4920 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004921}
4922
4923/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004924 * Ensure the correct coordinate spaces are used by InputDispatcher.
4925 *
4926 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4927 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4928 * space.
4929 */
4930class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4931public:
4932 void SetUp() override {
4933 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004934 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004935 }
4936
4937 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4938 gui::DisplayInfo info;
4939 info.displayId = displayId;
4940 info.transform = transform;
4941 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004942 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004943 }
4944
4945 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4946 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004947 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004948 }
4949
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004950 void removeAllWindowsAndDisplays() {
4951 mDisplayInfos.clear();
4952 mWindowInfos.clear();
4953 }
4954
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004955 // Set up a test scenario where the display has a scaled projection and there are two windows
4956 // on the display.
4957 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4958 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4959 // respectively.
4960 ui::Transform displayTransform;
4961 displayTransform.set(2, 0, 0, 4);
4962 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4963
4964 std::shared_ptr<FakeApplicationHandle> application =
4965 std::make_shared<FakeApplicationHandle>();
4966
4967 // Add two windows to the display. Their frames are represented in the display space.
4968 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004969 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4970 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004971 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4972 addWindow(firstWindow);
4973
4974 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004975 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4976 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004977 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4978 addWindow(secondWindow);
4979 return {std::move(firstWindow), std::move(secondWindow)};
4980 }
4981
4982private:
4983 std::vector<gui::DisplayInfo> mDisplayInfos;
4984 std::vector<gui::WindowInfo> mWindowInfos;
4985};
4986
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004987TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004988 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4989 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004990 // selected so that if the hit test was performed with the point and the bounds being in
4991 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004992 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4993 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4994 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004995
4996 firstWindow->consumeMotionDown();
4997 secondWindow->assertNoEvents();
4998}
4999
5000// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5001// the event should be treated as being in the logical display space.
5002TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5003 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5004 // Send down to the first window. The point is represented in the logical display space. The
5005 // point is selected so that if the hit test was done in logical display space, then it would
5006 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005007 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005008 PointF{75 * 2, 55 * 4});
5009
5010 firstWindow->consumeMotionDown();
5011 secondWindow->assertNoEvents();
5012}
5013
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005014// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5015// event should be treated as being in the logical display space.
5016TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5017 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5018
5019 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5020 ui::Transform injectedEventTransform;
5021 injectedEventTransform.set(matrix);
5022 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5023 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5024
5025 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5026 .displayId(ADISPLAY_ID_DEFAULT)
5027 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005028 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005029 .x(untransformedPoint.x)
5030 .y(untransformedPoint.y))
5031 .build();
5032 event.transform(matrix);
5033
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005034 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005035 InputEventInjectionSync::WAIT_FOR_RESULT);
5036
5037 firstWindow->consumeMotionDown();
5038 secondWindow->assertNoEvents();
5039}
5040
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005041TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5042 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5043
5044 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005045 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5046 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5047 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005048
5049 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005050 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5051 ASSERT_NE(nullptr, event);
5052 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005053
5054 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005055 EXPECT_EQ(300, event->getRawX(0));
5056 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005057
5058 // Ensure that the x and y values are in the window's coordinate space.
5059 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5060 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005061 EXPECT_EQ(100, event->getX(0));
5062 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005063}
5064
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005065TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5066 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5067 // The monitor will always receive events in the logical display's coordinate space, because
5068 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005069 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005070
5071 // Send down to the first window.
5072 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5073 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5074 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5075 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5076
5077 // Second pointer goes down on second window.
5078 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5079 ADISPLAY_ID_DEFAULT,
5080 {PointF{50, 100}, PointF{150, 220}}));
5081 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5082 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5083 {1, PointF{300, 880}}};
5084 monitor.consumeMotionEvent(
5085 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5086
5087 mDispatcher->cancelCurrentTouch();
5088
5089 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5090 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5091 monitor.consumeMotionEvent(
5092 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5093}
5094
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005095TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5096 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5097
5098 // Send down to the first window.
5099 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5100 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5101 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5102
5103 // The pointer is transferred to the second window, and the second window receives it in the
5104 // correct coordinate space.
5105 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5106 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5107 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5108}
5109
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005110TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5111 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5112
5113 // Send hover move to the second window, and ensure it shows up as hover enter.
5114 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5115 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5116 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5117 WithCoords(100, 80), WithRawCoords(300, 880)));
5118
5119 // Touch down at the same location and ensure a hover exit is synthesized.
5120 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5121 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5122 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5123 WithRawCoords(300, 880)));
5124 secondWindow->consumeMotionEvent(
5125 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5126 secondWindow->assertNoEvents();
5127 firstWindow->assertNoEvents();
5128}
5129
Prabir Pradhan453ae732023-10-13 14:30:14 +00005130// Same as above, but while the window is being mirrored.
5131TEST_F(InputDispatcherDisplayProjectionTest,
5132 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5133 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5134
5135 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5136 ui::Transform secondDisplayTransform;
5137 secondDisplayTransform.set(matrix);
5138 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5139
5140 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5141 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5142 addWindow(secondWindowClone);
5143
5144 // Send hover move to the second window, and ensure it shows up as hover enter.
5145 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5146 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5147 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5148 WithCoords(100, 80), WithRawCoords(300, 880)));
5149
5150 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5151 // display.
5152 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5153 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5154 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5155 WithRawCoords(300, 880)));
5156 secondWindow->consumeMotionEvent(
5157 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5158 secondWindow->assertNoEvents();
5159 firstWindow->assertNoEvents();
5160}
5161
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005162TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5163 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5164
5165 // Send hover enter to second window
5166 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5167 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5168 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5169 WithCoords(100, 80), WithRawCoords(300, 880)));
5170
5171 mDispatcher->cancelCurrentTouch();
5172
5173 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5174 WithRawCoords(300, 880)));
5175 secondWindow->assertNoEvents();
5176 firstWindow->assertNoEvents();
5177}
5178
Prabir Pradhan453ae732023-10-13 14:30:14 +00005179// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005180TEST_F(InputDispatcherDisplayProjectionTest,
5181 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5182 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5183
5184 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5185 ui::Transform secondDisplayTransform;
5186 secondDisplayTransform.set(matrix);
5187 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5188
5189 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5190 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5191 addWindow(secondWindowClone);
5192
5193 // Send hover enter to second window
5194 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5195 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5196 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5197 WithCoords(100, 80), WithRawCoords(300, 880),
5198 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5199
5200 mDispatcher->cancelCurrentTouch();
5201
5202 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5203 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5204 WithRawCoords(300, 880),
5205 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5206 secondWindow->assertNoEvents();
5207 firstWindow->assertNoEvents();
5208}
5209
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005210/** Ensure consistent behavior of InputDispatcher in all orientations. */
5211class InputDispatcherDisplayOrientationFixture
5212 : public InputDispatcherDisplayProjectionTest,
5213 public ::testing::WithParamInterface<ui::Rotation> {};
5214
5215// This test verifies the touchable region of a window for all rotations of the display by tapping
5216// in different locations on the display, specifically points close to the four corners of a
5217// window.
5218TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5219 constexpr static int32_t displayWidth = 400;
5220 constexpr static int32_t displayHeight = 800;
5221
5222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5223
5224 const auto rotation = GetParam();
5225
5226 // Set up the display with the specified rotation.
5227 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5228 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5229 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5230 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5231 logicalDisplayWidth, logicalDisplayHeight);
5232 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5233
5234 // Create a window with its bounds determined in the logical display.
5235 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5236 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5237 sp<FakeWindowHandle> window =
5238 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5239 window->setFrame(frameInDisplay, displayTransform);
5240 addWindow(window);
5241
5242 // The following points in logical display space should be inside the window.
5243 static const std::array<vec2, 4> insidePoints{
5244 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5245 for (const auto pointInsideWindow : insidePoints) {
5246 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5247 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005248 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5249 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5250 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005251 window->consumeMotionDown();
5252
Prabir Pradhan678438e2023-04-13 19:32:51 +00005253 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5254 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5255 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005256 window->consumeMotionUp();
5257 }
5258
5259 // The following points in logical display space should be outside the window.
5260 static const std::array<vec2, 5> outsidePoints{
5261 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5262 for (const auto pointOutsideWindow : outsidePoints) {
5263 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5264 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5266 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5267 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005268
Prabir Pradhan678438e2023-04-13 19:32:51 +00005269 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5270 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5271 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005272 }
5273 window->assertNoEvents();
5274}
5275
5276// Run the precision tests for all rotations.
5277INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5278 InputDispatcherDisplayOrientationFixture,
5279 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5280 ui::ROTATION_270),
5281 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5282 return ftl::enum_string(testParamInfo.param);
5283 });
5284
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005285using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5286 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005287
5288class TransferTouchFixture : public InputDispatcherTest,
5289 public ::testing::WithParamInterface<TransferFunction> {};
5290
5291TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005293
5294 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005295 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005296 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5297 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005298 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005299 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005300 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5301 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005302 sp<FakeWindowHandle> wallpaper =
5303 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5304 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005305 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005306 mDispatcher->onWindowInfosChanged(
5307 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005308
5309 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005310 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5311 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005312
Svet Ganov5d3bc372020-01-26 23:11:07 -08005313 // Only the first window should get the down event
5314 firstWindow->consumeMotionDown();
5315 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005316 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005317
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005318 // Transfer touch to the second window
5319 TransferFunction f = GetParam();
5320 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5321 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005322 // The first window gets cancel and the second gets down
5323 firstWindow->consumeMotionCancel();
5324 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005325 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005326
5327 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005328 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5329 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005330 // The first window gets no events and the second gets up
5331 firstWindow->assertNoEvents();
5332 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005333 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005334}
5335
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005336/**
5337 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5338 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5339 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5340 * natural to the user.
5341 * In this test, we are sending a pointer to both spy window and first window. We then try to
5342 * transfer touch to the second window. The dispatcher should identify the first window as the
5343 * one that should lose the gesture, and therefore the action should be to move the gesture from
5344 * the first window to the second.
5345 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5346 * the other API, as well.
5347 */
5348TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5350
5351 // Create a couple of windows + a spy window
5352 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005353 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005354 spyWindow->setTrustedOverlay(true);
5355 spyWindow->setSpy(true);
5356 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005357 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005358 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005359 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005360
5361 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005362 mDispatcher->onWindowInfosChanged(
5363 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005364
5365 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005366 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5367 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005368 // Only the first window and spy should get the down event
5369 spyWindow->consumeMotionDown();
5370 firstWindow->consumeMotionDown();
5371
5372 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5373 // if f === 'transferTouch'.
5374 TransferFunction f = GetParam();
5375 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5376 ASSERT_TRUE(success);
5377 // The first window gets cancel and the second gets down
5378 firstWindow->consumeMotionCancel();
5379 secondWindow->consumeMotionDown();
5380
5381 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005382 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5383 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005384 // The first window gets no events and the second+spy get up
5385 firstWindow->assertNoEvents();
5386 spyWindow->consumeMotionUp();
5387 secondWindow->consumeMotionUp();
5388}
5389
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005390TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005391 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005392
5393 PointF touchPoint = {10, 10};
5394
5395 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005396 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005397 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5398 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005399 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005400 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005401 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5402 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005403 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005404
5405 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005406 mDispatcher->onWindowInfosChanged(
5407 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005408
5409 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005410 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5411 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5412 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005413 // Only the first window should get the down event
5414 firstWindow->consumeMotionDown();
5415 secondWindow->assertNoEvents();
5416
5417 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005418 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5419 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005420 // Only the first window should get the pointer down event
5421 firstWindow->consumeMotionPointerDown(1);
5422 secondWindow->assertNoEvents();
5423
5424 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005425 TransferFunction f = GetParam();
5426 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5427 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005428 // The first window gets cancel and the second gets down and pointer down
5429 firstWindow->consumeMotionCancel();
5430 secondWindow->consumeMotionDown();
5431 secondWindow->consumeMotionPointerDown(1);
5432
5433 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005434 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5435 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005436 // The first window gets nothing and the second gets pointer up
5437 firstWindow->assertNoEvents();
5438 secondWindow->consumeMotionPointerUp(1);
5439
5440 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005441 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5442 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005443 // The first window gets nothing and the second gets up
5444 firstWindow->assertNoEvents();
5445 secondWindow->consumeMotionUp();
5446}
5447
Arthur Hungc539dbb2022-12-08 07:45:36 +00005448TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5450
5451 // Create a couple of windows
5452 sp<FakeWindowHandle> firstWindow =
5453 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5454 ADISPLAY_ID_DEFAULT);
5455 firstWindow->setDupTouchToWallpaper(true);
5456 sp<FakeWindowHandle> secondWindow =
5457 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5458 ADISPLAY_ID_DEFAULT);
5459 secondWindow->setDupTouchToWallpaper(true);
5460
5461 sp<FakeWindowHandle> wallpaper1 =
5462 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5463 wallpaper1->setIsWallpaper(true);
5464
5465 sp<FakeWindowHandle> wallpaper2 =
5466 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5467 wallpaper2->setIsWallpaper(true);
5468 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005469 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5470 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5471 {},
5472 0,
5473 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005474
5475 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005476 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5477 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005478
5479 // Only the first window should get the down event
5480 firstWindow->consumeMotionDown();
5481 secondWindow->assertNoEvents();
5482 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5483 wallpaper2->assertNoEvents();
5484
5485 // Transfer touch focus to the second window
5486 TransferFunction f = GetParam();
5487 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5488 ASSERT_TRUE(success);
5489
5490 // The first window gets cancel and the second gets down
5491 firstWindow->consumeMotionCancel();
5492 secondWindow->consumeMotionDown();
5493 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5494 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5495
5496 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005497 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5498 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005499 // The first window gets no events and the second gets up
5500 firstWindow->assertNoEvents();
5501 secondWindow->consumeMotionUp();
5502 wallpaper1->assertNoEvents();
5503 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5504}
5505
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005506// For the cases of single pointer touch and two pointers non-split touch, the api's
5507// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5508// for the case where there are multiple pointers split across several windows.
5509INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5510 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005511 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5512 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005513 return dispatcher->transferTouch(destChannelToken,
5514 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005515 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005516 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5517 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005518 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005519 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005520 }));
5521
Svet Ganov5d3bc372020-01-26 23:11:07 -08005522TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005524
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005525 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005526 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5527 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005528 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005529
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005530 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005531 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5532 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005533 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005534
5535 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005536 mDispatcher->onWindowInfosChanged(
5537 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005538
5539 PointF pointInFirst = {300, 200};
5540 PointF pointInSecond = {300, 600};
5541
5542 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005543 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5544 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5545 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005546 // Only the first window should get the down event
5547 firstWindow->consumeMotionDown();
5548 secondWindow->assertNoEvents();
5549
5550 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005551 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5552 ADISPLAY_ID_DEFAULT,
5553 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005554 // The first window gets a move and the second a down
5555 firstWindow->consumeMotionMove();
5556 secondWindow->consumeMotionDown();
5557
5558 // Transfer touch focus to the second window
5559 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5560 // The first window gets cancel and the new gets pointer down (it already saw down)
5561 firstWindow->consumeMotionCancel();
5562 secondWindow->consumeMotionPointerDown(1);
5563
5564 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005565 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5566 ADISPLAY_ID_DEFAULT,
5567 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005568 // The first window gets nothing and the second gets pointer up
5569 firstWindow->assertNoEvents();
5570 secondWindow->consumeMotionPointerUp(1);
5571
5572 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005573 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5574 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005575 // The first window gets nothing and the second gets up
5576 firstWindow->assertNoEvents();
5577 secondWindow->consumeMotionUp();
5578}
5579
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005580// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5581// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5582// touch is not supported, so the touch should continue on those windows and the transferred-to
5583// window should get nothing.
5584TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5585 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5586
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005587 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005588 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5589 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005590 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005591
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005592 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005593 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5594 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005595 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005596
5597 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005598 mDispatcher->onWindowInfosChanged(
5599 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005600
5601 PointF pointInFirst = {300, 200};
5602 PointF pointInSecond = {300, 600};
5603
5604 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005605 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5606 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5607 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005608 // Only the first window should get the down event
5609 firstWindow->consumeMotionDown();
5610 secondWindow->assertNoEvents();
5611
5612 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005613 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5614 ADISPLAY_ID_DEFAULT,
5615 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005616 // The first window gets a move and the second a down
5617 firstWindow->consumeMotionMove();
5618 secondWindow->consumeMotionDown();
5619
5620 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005621 const bool transferred =
5622 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005623 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5624 ASSERT_FALSE(transferred);
5625 firstWindow->assertNoEvents();
5626 secondWindow->assertNoEvents();
5627
5628 // The rest of the dispatch should proceed as normal
5629 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005630 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5631 ADISPLAY_ID_DEFAULT,
5632 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005633 // The first window gets MOVE and the second gets pointer up
5634 firstWindow->consumeMotionMove();
5635 secondWindow->consumeMotionUp();
5636
5637 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005638 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5639 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005640 // The first window gets nothing and the second gets up
5641 firstWindow->consumeMotionUp();
5642 secondWindow->assertNoEvents();
5643}
5644
Arthur Hungabbb9d82021-09-01 14:52:30 +00005645// This case will create two windows and one mirrored window on the default display and mirror
5646// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5647// the windows info of second display before default display.
5648TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5650 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005651 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005652 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005653 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005654 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005655 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005656
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005657 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005658 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005659
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005660 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005661 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005662
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005663 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005664 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005665
5666 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005667 mDispatcher->onWindowInfosChanged(
5668 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5669 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5670 *secondWindowInPrimary->getInfo()},
5671 {},
5672 0,
5673 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005674
5675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005676 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005677 {50, 50}))
5678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5679
5680 // Window should receive motion event.
5681 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5682
5683 // Transfer touch focus
5684 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5685 secondWindowInPrimary->getToken()));
5686 // The first window gets cancel.
5687 firstWindowInPrimary->consumeMotionCancel();
5688 secondWindowInPrimary->consumeMotionDown();
5689
5690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005691 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005692 ADISPLAY_ID_DEFAULT, {150, 50}))
5693 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5694 firstWindowInPrimary->assertNoEvents();
5695 secondWindowInPrimary->consumeMotionMove();
5696
5697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005698 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005699 {150, 50}))
5700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5701 firstWindowInPrimary->assertNoEvents();
5702 secondWindowInPrimary->consumeMotionUp();
5703}
5704
5705// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5706// 'transferTouch' api.
5707TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5709 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005710 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005711 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005712 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005713 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005714 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005715
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005716 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005717 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005718
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005719 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005720 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005721
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005722 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005723 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005724
5725 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005726 mDispatcher->onWindowInfosChanged(
5727 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5728 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5729 *secondWindowInPrimary->getInfo()},
5730 {},
5731 0,
5732 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005733
5734 // Touch on second display.
5735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005736 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5737 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5739
5740 // Window should receive motion event.
5741 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5742
5743 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005744 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005745
5746 // The first window gets cancel.
5747 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5748 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5749
5750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005751 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005752 SECOND_DISPLAY_ID, {150, 50}))
5753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5754 firstWindowInPrimary->assertNoEvents();
5755 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5756
5757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005758 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5760 firstWindowInPrimary->assertNoEvents();
5761 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5762}
5763
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005764TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005766 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5767 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005768
Vishnu Nair47074b82020-08-14 11:54:47 -07005769 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005770 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005771 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005772
5773 window->consumeFocusEvent(true);
5774
Prabir Pradhan678438e2023-04-13 19:32:51 +00005775 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005776
5777 // Window should receive key down event.
5778 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005779
5780 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005781 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005782 mFakePolicy->assertUserActivityPoked();
5783}
5784
5785TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5787 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5788 "Fake Window", ADISPLAY_ID_DEFAULT);
5789
5790 window->setDisableUserActivity(true);
5791 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005792 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005793 setFocusedWindow(window);
5794
5795 window->consumeFocusEvent(true);
5796
5797 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5798
5799 // Window should receive key down event.
5800 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5801
5802 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005803 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005804 mFakePolicy->assertUserActivityNotPoked();
5805}
5806
5807TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5809 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5810 "Fake Window", ADISPLAY_ID_DEFAULT);
5811
5812 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005813 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005814 setFocusedWindow(window);
5815
5816 window->consumeFocusEvent(true);
5817
5818 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5819 mDispatcher->waitForIdle();
5820
5821 // System key is not passed down
5822 window->assertNoEvents();
5823
5824 // Should have poked user activity
5825 mFakePolicy->assertUserActivityPoked();
5826}
5827
5828TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5831 "Fake Window", ADISPLAY_ID_DEFAULT);
5832
5833 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005834 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005835 setFocusedWindow(window);
5836
5837 window->consumeFocusEvent(true);
5838
5839 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5840 mDispatcher->waitForIdle();
5841
5842 // System key is not passed down
5843 window->assertNoEvents();
5844
5845 // Should have poked user activity
5846 mFakePolicy->assertUserActivityPoked();
5847}
5848
5849TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5851 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5852 "Fake Window", ADISPLAY_ID_DEFAULT);
5853
5854 window->setDisableUserActivity(true);
5855 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005856 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005857 setFocusedWindow(window);
5858
5859 window->consumeFocusEvent(true);
5860
5861 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5862 mDispatcher->waitForIdle();
5863
5864 // System key is not passed down
5865 window->assertNoEvents();
5866
5867 // Should have poked user activity
5868 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005869}
5870
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005871TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5873 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5874 "Fake Window", ADISPLAY_ID_DEFAULT);
5875
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005876 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005877
5878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005879 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005880 ADISPLAY_ID_DEFAULT, {100, 100}))
5881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5882
5883 window->consumeMotionEvent(
5884 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5885
5886 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005887 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005888 mFakePolicy->assertUserActivityPoked();
5889}
5890
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005891TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005893 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5894 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005895
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005897
Prabir Pradhan678438e2023-04-13 19:32:51 +00005898 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005899 mDispatcher->waitForIdle();
5900
5901 window->assertNoEvents();
5902}
5903
5904// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5905TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005906 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005907 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5908 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005909
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005910 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005911
5912 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005913 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005914 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005915 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5916 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005917
5918 // Window should receive only the motion event
5919 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5920 window->assertNoEvents(); // Key event or focus event will not be received
5921}
5922
arthurhungea3f4fc2020-12-21 23:18:53 +08005923TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5925
arthurhungea3f4fc2020-12-21 23:18:53 +08005926 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005927 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5928 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005929 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005930
arthurhungea3f4fc2020-12-21 23:18:53 +08005931 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005932 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5933 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005934 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005935
5936 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005937 mDispatcher->onWindowInfosChanged(
5938 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005939
5940 PointF pointInFirst = {300, 200};
5941 PointF pointInSecond = {300, 600};
5942
5943 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005944 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5945 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5946 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005947 // Only the first window should get the down event
5948 firstWindow->consumeMotionDown();
5949 secondWindow->assertNoEvents();
5950
5951 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005952 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5953 ADISPLAY_ID_DEFAULT,
5954 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005955 // The first window gets a move and the second a down
5956 firstWindow->consumeMotionMove();
5957 secondWindow->consumeMotionDown();
5958
5959 // Send pointer cancel to the second window
5960 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005961 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005962 {pointInFirst, pointInSecond});
5963 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005964 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005965 // The first window gets move and the second gets cancel.
5966 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5967 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5968
5969 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005970 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5971 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005972 // The first window gets up and the second gets nothing.
5973 firstWindow->consumeMotionUp();
5974 secondWindow->assertNoEvents();
5975}
5976
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005977TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5979
5980 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005981 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005982 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005983 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5984 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5985 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5986
Harry Cutts33476232023-01-30 19:57:29 +00005987 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005988 window->assertNoEvents();
5989 mDispatcher->waitForIdle();
5990}
5991
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005992using InputDispatcherMonitorTest = InputDispatcherTest;
5993
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005994/**
5995 * Two entities that receive touch: A window, and a global monitor.
5996 * The touch goes to the window, and then the window disappears.
5997 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5998 * for the monitor, as well.
5999 * 1. foregroundWindow
6000 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6001 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006002TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6004 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006005 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006006
Prabir Pradhanfb549072023-10-05 19:17:36 +00006007 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006008
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006009 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006011 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006012 {100, 200}))
6013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6014
6015 // Both the foreground window and the global monitor should receive the touch down
6016 window->consumeMotionDown();
6017 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6018
6019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006020 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006021 ADISPLAY_ID_DEFAULT, {110, 200}))
6022 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6023
6024 window->consumeMotionMove();
6025 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6026
6027 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006028 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006029 window->consumeMotionCancel();
6030 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6031
6032 // If more events come in, there will be no more foreground window to send them to. This will
6033 // cause a cancel for the monitor, as well.
6034 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006035 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006036 ADISPLAY_ID_DEFAULT, {120, 200}))
6037 << "Injection should fail because the window was removed";
6038 window->assertNoEvents();
6039 // Global monitor now gets the cancel
6040 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6041}
6042
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006043TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006045 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6046 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006047 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006048
Prabir Pradhanfb549072023-10-05 19:17:36 +00006049 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006050
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006052 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006054 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006055 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006056}
6057
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006058TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006059 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006060
Chris Yea209fde2020-07-22 13:54:51 -07006061 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006062 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6063 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006064 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006065
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006067 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006069 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006070 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006071
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006072 // Pilfer pointers from the monitor.
6073 // This should not do anything and the window should continue to receive events.
6074 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006075
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006077 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006078 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006079 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006080
6081 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6082 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006083}
6084
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006085TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006087 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6088 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006089 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006090 window->setWindowOffset(20, 40);
6091 window->setWindowTransform(0, 1, -1, 0);
6092
Prabir Pradhanfb549072023-10-05 19:17:36 +00006093 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006094
6095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006096 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6098 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006099 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6100 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006101 // Even though window has transform, gesture monitor must not.
6102 ASSERT_EQ(ui::Transform(), event->getTransform());
6103}
6104
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006105TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006107 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006108
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006109 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006110 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006111 << "Injection should fail if there is a monitor, but no touchable window";
6112 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006113}
6114
chaviw81e2bb92019-12-18 15:03:51 -08006115TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006117 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6118 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006119
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006120 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006121
6122 NotifyMotionArgs motionArgs =
6123 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6124 ADISPLAY_ID_DEFAULT);
6125
Prabir Pradhan678438e2023-04-13 19:32:51 +00006126 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006127 // Window should receive motion down event.
6128 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6129
6130 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006131 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006132 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6133 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6134 motionArgs.pointerCoords[0].getX() - 10);
6135
Prabir Pradhan678438e2023-04-13 19:32:51 +00006136 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006137 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006138}
6139
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006140/**
6141 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6142 * the device default right away. In the test scenario, we check both the default value,
6143 * and the action of enabling / disabling.
6144 */
6145TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006147 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6148 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006149 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006150
6151 // Set focused application.
6152 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006153 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006154
6155 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006156 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006157 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006158 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006159
6160 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006161 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006162 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006163 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006164
6165 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006166 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006167 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006168 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006169 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006171 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006172 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006173
6174 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006175 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006177 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006178
6179 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006180 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006181 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006182 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006183 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006184 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006185 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006186 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006187
6188 window->assertNoEvents();
6189}
6190
Gang Wange9087892020-01-07 12:17:14 -05006191TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006192 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006193 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6194 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006195
6196 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006197 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006198
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006199 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006200 setFocusedWindow(window);
6201
Harry Cutts33476232023-01-30 19:57:29 +00006202 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006203
Prabir Pradhan678438e2023-04-13 19:32:51 +00006204 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6205 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006206
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006207 std::unique_ptr<KeyEvent> event = window->consumeKey();
6208 ASSERT_NE(event, nullptr);
6209 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006210 ASSERT_NE(verified, nullptr);
6211 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6212
6213 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6214 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6215 ASSERT_EQ(keyArgs.source, verified->source);
6216 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6217
6218 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6219
6220 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006221 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006222 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006223 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6224 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6225 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6226 ASSERT_EQ(0, verifiedKey.repeatCount);
6227}
6228
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006229TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006231 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6232 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006233
6234 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6235
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006236 ui::Transform transform;
6237 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6238
6239 gui::DisplayInfo displayInfo;
6240 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6241 displayInfo.transform = transform;
6242
Patrick Williamsd828f302023-04-28 17:52:08 -05006243 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006244
Prabir Pradhan678438e2023-04-13 19:32:51 +00006245 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006246 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6247 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006248 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006249
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006250 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6251 ASSERT_NE(nullptr, event);
6252 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006253 ASSERT_NE(verified, nullptr);
6254 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6255
6256 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6257 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6258 EXPECT_EQ(motionArgs.source, verified->source);
6259 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6260
6261 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6262
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006263 const vec2 rawXY =
6264 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6265 motionArgs.pointerCoords[0].getXYValue());
6266 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6267 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006268 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006269 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006270 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006271 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6272 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6273}
6274
chaviw09c8d2d2020-08-24 15:48:26 -07006275/**
6276 * Ensure that separate calls to sign the same data are generating the same key.
6277 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6278 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6279 * tests.
6280 */
6281TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6282 KeyEvent event = getTestKeyEvent();
6283 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6284
6285 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6286 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6287 ASSERT_EQ(hmac1, hmac2);
6288}
6289
6290/**
6291 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6292 */
6293TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6294 KeyEvent event = getTestKeyEvent();
6295 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6296 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6297
6298 verifiedEvent.deviceId += 1;
6299 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6300
6301 verifiedEvent.source += 1;
6302 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6303
6304 verifiedEvent.eventTimeNanos += 1;
6305 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6306
6307 verifiedEvent.displayId += 1;
6308 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6309
6310 verifiedEvent.action += 1;
6311 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6312
6313 verifiedEvent.downTimeNanos += 1;
6314 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6315
6316 verifiedEvent.flags += 1;
6317 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6318
6319 verifiedEvent.keyCode += 1;
6320 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6321
6322 verifiedEvent.scanCode += 1;
6323 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6324
6325 verifiedEvent.metaState += 1;
6326 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6327
6328 verifiedEvent.repeatCount += 1;
6329 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6330}
6331
Vishnu Nair958da932020-08-21 17:12:37 -07006332TEST_F(InputDispatcherTest, SetFocusedWindow) {
6333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6334 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006335 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006336 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006337 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006338 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6339
6340 // Top window is also focusable but is not granted focus.
6341 windowTop->setFocusable(true);
6342 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006343 mDispatcher->onWindowInfosChanged(
6344 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006345 setFocusedWindow(windowSecond);
6346
6347 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006349 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006350
6351 // Focused window should receive event.
6352 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6353 windowTop->assertNoEvents();
6354}
6355
6356TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6357 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6358 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006359 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006360 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6361
6362 window->setFocusable(true);
6363 // Release channel for window is no longer valid.
6364 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006365 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006366 setFocusedWindow(window);
6367
6368 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006369 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006370
6371 // window channel is invalid, so it should not receive any input event.
6372 window->assertNoEvents();
6373}
6374
6375TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6377 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006378 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006379 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006380 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6381
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006382 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006383 setFocusedWindow(window);
6384
6385 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006386 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006387
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006388 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006389 window->assertNoEvents();
6390}
6391
6392TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6393 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6394 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006395 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006396 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006397 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006398 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6399
6400 windowTop->setFocusable(true);
6401 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006402 mDispatcher->onWindowInfosChanged(
6403 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006404 setFocusedWindow(windowTop);
6405 windowTop->consumeFocusEvent(true);
6406
Chavi Weingarten847e8512023-03-29 00:26:09 +00006407 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006408 mDispatcher->onWindowInfosChanged(
6409 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006410 windowSecond->consumeFocusEvent(true);
6411 windowTop->consumeFocusEvent(false);
6412
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006414 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006415
6416 // Focused window should receive event.
6417 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6418}
6419
Chavi Weingarten847e8512023-03-29 00:26:09 +00006420TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6422 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006423 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006424 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006425 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006426 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6427
6428 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006429 windowSecond->setFocusable(false);
6430 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006431 mDispatcher->onWindowInfosChanged(
6432 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006433 setFocusedWindow(windowTop);
6434 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006435
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006436 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006437 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006438
6439 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006440 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006441 windowSecond->assertNoEvents();
6442}
6443
6444TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6446 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006447 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006448 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006449 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6450 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006451 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6452
6453 window->setFocusable(true);
6454 previousFocusedWindow->setFocusable(true);
6455 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006456 mDispatcher->onWindowInfosChanged(
6457 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006458 setFocusedWindow(previousFocusedWindow);
6459 previousFocusedWindow->consumeFocusEvent(true);
6460
6461 // Requesting focus on invisible window takes focus from currently focused window.
6462 setFocusedWindow(window);
6463 previousFocusedWindow->consumeFocusEvent(false);
6464
6465 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006467 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6468 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006469
6470 // Window does not get focus event or key down.
6471 window->assertNoEvents();
6472
6473 // Window becomes visible.
6474 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006475 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006476
6477 // Window receives focus event.
6478 window->consumeFocusEvent(true);
6479 // Focused window receives key down.
6480 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6481}
6482
Vishnu Nair599f1412021-06-21 10:39:58 -07006483TEST_F(InputDispatcherTest, DisplayRemoved) {
6484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6485 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006486 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006487 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6488
6489 // window is granted focus.
6490 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006491 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006492 setFocusedWindow(window);
6493 window->consumeFocusEvent(true);
6494
6495 // When a display is removed window loses focus.
6496 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6497 window->consumeFocusEvent(false);
6498}
6499
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006500/**
6501 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6502 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6503 * of the 'slipperyEnterWindow'.
6504 *
6505 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6506 * a way so that the touched location is no longer covered by the top window.
6507 *
6508 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6509 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6510 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6511 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6512 * with ACTION_DOWN).
6513 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6514 * window moved itself away from the touched location and had Flag::SLIPPERY.
6515 *
6516 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6517 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6518 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6519 *
6520 * In this test, we ensure that the event received by the bottom window has
6521 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6522 */
6523TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006524 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006525 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006526
6527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6528 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6529
6530 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006531 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006532 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006533 // Make sure this one overlaps the bottom window
6534 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6535 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6536 // one. Windows with the same owner are not considered to be occluding each other.
6537 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6538
6539 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006540 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006541 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6542
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006543 mDispatcher->onWindowInfosChanged(
6544 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006545
6546 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006547 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6548 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6549 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006550 slipperyExitWindow->consumeMotionDown();
6551 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006552 mDispatcher->onWindowInfosChanged(
6553 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006554
Prabir Pradhan678438e2023-04-13 19:32:51 +00006555 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6556 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6557 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006558
6559 slipperyExitWindow->consumeMotionCancel();
6560
6561 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6562 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6563}
6564
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006565/**
6566 * Two windows, one on the left and another on the right. The left window is slippery. The right
6567 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6568 * touch moves from the left window into the right window, the gesture should continue to go to the
6569 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6570 * reproduces a crash.
6571 */
6572TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6573 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6574
6575 sp<FakeWindowHandle> leftSlipperyWindow =
6576 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6577 leftSlipperyWindow->setSlippery(true);
6578 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6579
6580 sp<FakeWindowHandle> rightDropTouchesWindow =
6581 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6582 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6583 rightDropTouchesWindow->setDropInput(true);
6584
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006585 mDispatcher->onWindowInfosChanged(
6586 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006587
6588 // Start touch in the left window
6589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6590 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6591 .build());
6592 leftSlipperyWindow->consumeMotionDown();
6593
6594 // And move it into the right window
6595 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6596 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6597 .build());
6598
6599 // Since the right window isn't eligible to receive input, touch does not slip.
6600 // The left window continues to receive the gesture.
6601 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6602 rightDropTouchesWindow->assertNoEvents();
6603}
6604
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006605/**
6606 * A single window is on screen first. Touch is injected into that window. Next, a second window
6607 * appears. Since the first window is slippery, touch will move from the first window to the second.
6608 */
6609TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6610 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6611 sp<FakeWindowHandle> originalWindow =
6612 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6613 originalWindow->setFrame(Rect(0, 0, 200, 200));
6614 originalWindow->setSlippery(true);
6615
6616 sp<FakeWindowHandle> appearingWindow =
6617 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6618 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6619
6620 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6621
6622 // Touch down on the original window
6623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6624 injectMotionEvent(*mDispatcher,
6625 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6626 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6627 .build()));
6628 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6629
6630 // Now, a new window appears. This could be, for example, a notification shade that appears
6631 // after user starts to drag down on the launcher window.
6632 mDispatcher->onWindowInfosChanged(
6633 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6635 injectMotionEvent(*mDispatcher,
6636 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6637 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6638 .build()));
6639 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6640 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6642 injectMotionEvent(*mDispatcher,
6643 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6644 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6645 .build()));
6646 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6647
6648 originalWindow->assertNoEvents();
6649 appearingWindow->assertNoEvents();
6650}
6651
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006652TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006653 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6655
6656 sp<FakeWindowHandle> leftWindow =
6657 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6658 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006659 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006660
6661 sp<FakeWindowHandle> rightSpy =
6662 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6663 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006664 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006665 rightSpy->setSpy(true);
6666 rightSpy->setTrustedOverlay(true);
6667
6668 sp<FakeWindowHandle> rightWindow =
6669 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6670 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006671 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006673 mDispatcher->onWindowInfosChanged(
6674 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006675
6676 // Touch in the left window
6677 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6678 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6679 .build());
6680 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6681 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006682 ASSERT_NO_FATAL_FAILURE(
6683 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006684
6685 // Touch another finger over the right windows
6686 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6687 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6688 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6689 .build());
6690 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6691 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6692 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6693 mDispatcher->waitForIdle();
6694 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006695 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6696 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006697
6698 // Release finger over left window. The UP actions are not treated as device interaction.
6699 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6700 // is part of the UP action, we do not treat this as device interaction.
6701 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6702 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6703 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6704 .build());
6705 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6706 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6707 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6708 mDispatcher->waitForIdle();
6709 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6710
6711 // Move remaining finger
6712 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6713 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6714 .build());
6715 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6716 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6717 mDispatcher->waitForIdle();
6718 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006719 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006720
6721 // Release all fingers
6722 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6723 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6724 .build());
6725 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6726 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6727 mDispatcher->waitForIdle();
6728 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6729}
6730
6731TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6733
6734 sp<FakeWindowHandle> window =
6735 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6736 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006737 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006738
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006739 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006740 setFocusedWindow(window);
6741 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6742
6743 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6744 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6745 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006746 ASSERT_NO_FATAL_FAILURE(
6747 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006748
6749 // The UP actions are not treated as device interaction.
6750 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6751 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6752 mDispatcher->waitForIdle();
6753 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6754}
6755
Prabir Pradhan5893d362023-11-17 04:30:40 +00006756TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6758
6759 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6760 ADISPLAY_ID_DEFAULT);
6761 left->setFrame(Rect(0, 0, 100, 100));
6762 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6763 "Right Window", ADISPLAY_ID_DEFAULT);
6764 right->setFrame(Rect(100, 0, 200, 100));
6765 sp<FakeWindowHandle> spy =
6766 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6767 spy->setFrame(Rect(0, 0, 200, 100));
6768 spy->setTrustedOverlay(true);
6769 spy->setSpy(true);
6770
6771 mDispatcher->onWindowInfosChanged(
6772 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6773
6774 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6775 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6776 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6777 mDispatcher->notifyMotion(notifyArgs);
6778
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006779 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00006780 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6781 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006782 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00006783 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6784 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006785 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00006786 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6787
6788 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6789 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6790 {PointF{150, 50}});
6791 mDispatcher->notifyMotion(notifyArgs);
6792
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006793 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00006794 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6795 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006796 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00006797 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6798 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006799 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00006800 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6801
6802 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6803}
6804
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006805class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6806protected:
6807 std::shared_ptr<FakeApplicationHandle> mApp;
6808 sp<FakeWindowHandle> mWindow;
6809
6810 virtual void SetUp() override {
6811 InputDispatcherTest::SetUp();
6812
6813 mApp = std::make_shared<FakeApplicationHandle>();
6814
6815 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6816 mWindow->setFrame(Rect(0, 0, 100, 100));
6817
6818 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6819 setFocusedWindow(mWindow);
6820 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6821 }
6822
6823 void setFallback(int32_t keycode) {
6824 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6825 return KeyEventBuilder(event).keyCode(keycode).build();
6826 });
6827 }
6828
6829 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006830 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
6831 ASSERT_NE(nullptr, event);
6832 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006833 }
6834};
6835
6836TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6837 mDispatcher->notifyKey(
6838 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6839 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6840 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6841}
6842
6843TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6844 mDispatcher->notifyKey(
6845 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6846 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6847 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6848}
6849
6850TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6851 mDispatcher->notifyKey(
6852 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6853
6854 // Do not handle this key event.
6855 consumeKey(/*handled=*/false,
6856 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6857 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6858
6859 // Since the policy did not request any fallback to be generated, ensure there are no events.
6860 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6861}
6862
6863TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6864 setFallback(AKEYCODE_B);
6865 mDispatcher->notifyKey(
6866 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6867
6868 // Do not handle this key event.
6869 consumeKey(/*handled=*/false,
6870 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6871
6872 // Since the key was not handled, ensure the fallback event was dispatched instead.
6873 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6874 consumeKey(/*handled=*/true,
6875 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6876 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6877
6878 // Release the original key, and ensure the fallback key is also released.
6879 mDispatcher->notifyKey(
6880 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6881 consumeKey(/*handled=*/false,
6882 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6883 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6884 consumeKey(/*handled=*/true,
6885 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6886 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6887
6888 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6889 mWindow->assertNoEvents();
6890}
6891
6892TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6893 setFallback(AKEYCODE_B);
6894 mDispatcher->notifyKey(
6895 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6896
6897 // Do not handle this key event, but handle the fallback.
6898 consumeKey(/*handled=*/false,
6899 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6900 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6901 consumeKey(/*handled=*/true,
6902 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6903 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6904
6905 // Release the original key, and ensure the fallback key is also released.
6906 mDispatcher->notifyKey(
6907 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6908 // But this time, the app handles the original key.
6909 consumeKey(/*handled=*/true,
6910 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6911 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6912 // Ensure the fallback key is canceled.
6913 consumeKey(/*handled=*/true,
6914 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6915 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6916
6917 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6918 mWindow->assertNoEvents();
6919}
6920
6921TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6922 setFallback(AKEYCODE_B);
6923 mDispatcher->notifyKey(
6924 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6925
6926 // Do not handle this key event.
6927 consumeKey(/*handled=*/false,
6928 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6929 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6930 // App does not handle the fallback either, so ensure another fallback is not generated.
6931 setFallback(AKEYCODE_C);
6932 consumeKey(/*handled=*/false,
6933 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6934 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6935
6936 // Release the original key, and ensure the fallback key is also released.
6937 setFallback(AKEYCODE_B);
6938 mDispatcher->notifyKey(
6939 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6940 consumeKey(/*handled=*/false,
6941 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6942 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6943 consumeKey(/*handled=*/false,
6944 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6945 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6946
6947 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6948 mWindow->assertNoEvents();
6949}
6950
6951TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6952 setFallback(AKEYCODE_B);
6953 mDispatcher->notifyKey(
6954 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6955
6956 // Do not handle this key event, so fallback is generated.
6957 consumeKey(/*handled=*/false,
6958 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6959 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6960 consumeKey(/*handled=*/true,
6961 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6962 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6963
6964 // Release the original key, but assume the policy is misbehaving and it
6965 // generates an inconsistent fallback to the one from the DOWN event.
6966 setFallback(AKEYCODE_C);
6967 mDispatcher->notifyKey(
6968 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6969 consumeKey(/*handled=*/false,
6970 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6971 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6972 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6973 consumeKey(/*handled=*/true,
6974 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6975 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6976
6977 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6978 mWindow->assertNoEvents();
6979}
6980
6981TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6982 setFallback(AKEYCODE_B);
6983 mDispatcher->notifyKey(
6984 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6985
6986 // Do not handle this key event, so fallback is generated.
6987 consumeKey(/*handled=*/false,
6988 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6990 consumeKey(/*handled=*/true,
6991 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6992 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6993
6994 // The original key is canceled.
6995 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6996 .keyCode(AKEYCODE_A)
6997 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6998 .build());
6999 consumeKey(/*handled=*/false,
7000 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7001 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7002 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7003 // Ensure the fallback key is also canceled due to the original key being canceled.
7004 consumeKey(/*handled=*/true,
7005 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7006 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7007
7008 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7009 mWindow->assertNoEvents();
7010}
7011
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007012TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7013 setFallback(AKEYCODE_B);
7014 mDispatcher->notifyKey(
7015 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7016
7017 // Do not handle this key event.
7018 consumeKey(/*handled=*/false,
7019 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7020 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7021 consumeKey(/*handled=*/true,
7022 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7023 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7024
7025 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7026 // When the unhandled key is reported to the policy next, remove the input channel.
7027 mDispatcher->removeInputChannel(mWindow->getToken());
7028 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7029 });
7030 // Release the original key, and let the app now handle the previously unhandled key.
7031 // This should result in the previously generated fallback key to be cancelled.
7032 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7033 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7034 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7035 // the policy call, we will now remove the input channel. Once the policy call returns, the
7036 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7037 // not cause any crashes.
7038 mDispatcher->notifyKey(
7039 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7040 consumeKey(/*handled=*/true,
7041 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7042 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7043}
7044
Garfield Tan1c7bc862020-01-28 13:24:04 -08007045class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7046protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007047 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7048 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007049
Chris Yea209fde2020-07-22 13:54:51 -07007050 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007051 sp<FakeWindowHandle> mWindow;
7052
7053 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00007054 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00007055 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00007056 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09007057 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007058 ASSERT_EQ(OK, mDispatcher->start());
7059
7060 setUpWindow();
7061 }
7062
7063 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007064 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007065 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007066
Vishnu Nair47074b82020-08-14 11:54:47 -07007067 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007068 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007069 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007070 mWindow->consumeFocusEvent(true);
7071 }
7072
Chris Ye2ad95392020-09-01 13:44:44 -07007073 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007074 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007075 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007076 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007077 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007078
7079 // Window should receive key down event.
7080 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7081 }
7082
7083 void expectKeyRepeatOnce(int32_t repeatCount) {
7084 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007085 mWindow->consumeKeyEvent(
7086 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007087 }
7088
Chris Ye2ad95392020-09-01 13:44:44 -07007089 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007090 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007091 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007092 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007093 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007094
7095 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007096 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007097 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007098 }
7099};
7100
7101TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007102 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007103 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7104 expectKeyRepeatOnce(repeatCount);
7105 }
7106}
7107
7108TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007109 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007110 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7111 expectKeyRepeatOnce(repeatCount);
7112 }
Harry Cutts33476232023-01-30 19:57:29 +00007113 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007114 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007115 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7116 expectKeyRepeatOnce(repeatCount);
7117 }
7118}
7119
7120TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007121 sendAndConsumeKeyDown(/*deviceId=*/1);
7122 expectKeyRepeatOnce(/*repeatCount=*/1);
7123 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007124 mWindow->assertNoEvents();
7125}
7126
7127TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007128 sendAndConsumeKeyDown(/*deviceId=*/1);
7129 expectKeyRepeatOnce(/*repeatCount=*/1);
7130 sendAndConsumeKeyDown(/*deviceId=*/2);
7131 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007132 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007133 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007134 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007135 expectKeyRepeatOnce(/*repeatCount=*/2);
7136 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007137 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007138 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007139 mWindow->assertNoEvents();
7140}
7141
7142TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007143 sendAndConsumeKeyDown(/*deviceId=*/1);
7144 expectKeyRepeatOnce(/*repeatCount=*/1);
7145 sendAndConsumeKeyDown(/*deviceId=*/2);
7146 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007147 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007148 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007149 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007150 mWindow->assertNoEvents();
7151}
7152
liushenxiang42232912021-05-21 20:24:09 +08007153TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7154 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007155 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007156 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007157 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7158 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7159 mWindow->assertNoEvents();
7160}
7161
Garfield Tan1c7bc862020-01-28 13:24:04 -08007162TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007163 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007164 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007165 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007166 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7167 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007168 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007169 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007170 }
7171}
7172
7173TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007174 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007175 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007176
7177 std::unordered_set<int32_t> idSet;
7178 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007179 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7180 ASSERT_NE(nullptr, repeatEvent);
7181 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007182 EXPECT_EQ(idSet.end(), idSet.find(id));
7183 idSet.insert(id);
7184 }
7185}
7186
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007187/* Test InputDispatcher for MultiDisplay */
7188class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7189public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007190 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007191 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007192
Chris Yea209fde2020-07-22 13:54:51 -07007193 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007194 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007195 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007196
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007197 // Set focus window for primary display, but focused display would be second one.
7198 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007199 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007200 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7201
Vishnu Nair958da932020-08-21 17:12:37 -07007202 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007203 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007204
Chris Yea209fde2020-07-22 13:54:51 -07007205 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007206 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007207 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007208 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007209 // Set focus display to second one.
7210 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7211 // Set focus window for second display.
7212 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007213 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007214 mDispatcher->onWindowInfosChanged(
7215 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007216 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007217 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007218 }
7219
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007220 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007221 InputDispatcherTest::TearDown();
7222
Chris Yea209fde2020-07-22 13:54:51 -07007223 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007224 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007225 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007226 windowInSecondary.clear();
7227 }
7228
7229protected:
Chris Yea209fde2020-07-22 13:54:51 -07007230 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007231 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007232 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007233 sp<FakeWindowHandle> windowInSecondary;
7234};
7235
7236TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7237 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007239 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007240 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007241 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007242 windowInSecondary->assertNoEvents();
7243
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007244 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007246 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007248 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007249 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007250}
7251
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007252TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007253 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007255 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007256 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007257 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007258 windowInSecondary->assertNoEvents();
7259
7260 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007262 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007263 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007264 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007265
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007266 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007267 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007268
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007269 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007270 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007271
7272 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007273 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007274 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007275 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007276 windowInSecondary->assertNoEvents();
7277}
7278
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007279// Test per-display input monitors for motion event.
7280TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007281 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007282 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007283 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007284 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007285
7286 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007288 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007289 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007290 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007291 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007292 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007293 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007294
7295 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007297 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007298 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007299 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007300 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007301 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007302 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007303
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007304 // Lift up the touch from the second display
7305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007306 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007307 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7308 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7309 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7310
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007311 // Test inject a non-pointer motion event.
7312 // If specific a display, it will dispatch to the focused window of particular display,
7313 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007315 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007317 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007318 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007319 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007320 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007321}
7322
7323// Test per-display input monitors for key event.
7324TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007325 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007326 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007327 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007328 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007329 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007330
7331 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007333 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007334 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007335 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007336 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007337 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007338}
7339
Vishnu Nair958da932020-08-21 17:12:37 -07007340TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7341 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007342 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007343 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007344 mDispatcher->onWindowInfosChanged(
7345 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7346 *windowInSecondary->getInfo()},
7347 {},
7348 0,
7349 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007350 setFocusedWindow(secondWindowInPrimary);
7351 windowInPrimary->consumeFocusEvent(false);
7352 secondWindowInPrimary->consumeFocusEvent(true);
7353
7354 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7356 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007357 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007358 windowInPrimary->assertNoEvents();
7359 windowInSecondary->assertNoEvents();
7360 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7361}
7362
Arthur Hungdfd528e2021-12-08 13:23:04 +00007363TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7364 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007365 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007366 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007367 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007368
7369 // Test touch down on primary display.
7370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007371 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007372 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7373 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7374 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7375
7376 // Test touch down on second display.
7377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007378 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007379 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7380 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7381 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7382
7383 // Trigger cancel touch.
7384 mDispatcher->cancelCurrentTouch();
7385 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7386 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7387 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7388 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7389
7390 // Test inject a move motion event, no window/monitor should receive the event.
7391 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007392 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007393 ADISPLAY_ID_DEFAULT, {110, 200}))
7394 << "Inject motion event should return InputEventInjectionResult::FAILED";
7395 windowInPrimary->assertNoEvents();
7396 monitorInPrimary.assertNoEvents();
7397
7398 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007399 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007400 SECOND_DISPLAY_ID, {110, 200}))
7401 << "Inject motion event should return InputEventInjectionResult::FAILED";
7402 windowInSecondary->assertNoEvents();
7403 monitorInSecondary.assertNoEvents();
7404}
7405
Hu Guocb134f12023-12-23 13:42:44 +00007406/**
7407 * Send a key to the primary display and to the secondary display.
7408 * Then cause the key on the primary display to be canceled by sending in a stale key.
7409 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7410 * does not get canceled.
7411 */
7412TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7413 // Send a key down on primary display
7414 mDispatcher->notifyKey(
7415 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7416 .displayId(ADISPLAY_ID_DEFAULT)
7417 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7418 .build());
7419 windowInPrimary->consumeKeyEvent(
7420 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7421 windowInSecondary->assertNoEvents();
7422
7423 // Send a key down on second display
7424 mDispatcher->notifyKey(
7425 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7426 .displayId(SECOND_DISPLAY_ID)
7427 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7428 .build());
7429 windowInSecondary->consumeKeyEvent(
7430 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7431 windowInPrimary->assertNoEvents();
7432
7433 // Send a valid key up event on primary display that will be dropped because it is stale
7434 NotifyKeyArgs staleKeyUp =
7435 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7436 .displayId(ADISPLAY_ID_DEFAULT)
7437 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7438 .build();
7439 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7440 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7441 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7442 mDispatcher->notifyKey(staleKeyUp);
7443
7444 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7445 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7446 // receive any events.
7447 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7448 WithDisplayId(ADISPLAY_ID_DEFAULT),
7449 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7450 windowInSecondary->assertNoEvents();
7451}
7452
7453/**
7454 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7455 */
7456TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7457 // Send touch down on primary display.
7458 mDispatcher->notifyMotion(
7459 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7460 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7461 .displayId(ADISPLAY_ID_DEFAULT)
7462 .build());
7463 windowInPrimary->consumeMotionEvent(
7464 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7465 windowInSecondary->assertNoEvents();
7466
7467 // Send touch down on second display.
7468 mDispatcher->notifyMotion(
7469 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7470 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7471 .displayId(SECOND_DISPLAY_ID)
7472 .build());
7473 windowInPrimary->assertNoEvents();
7474 windowInSecondary->consumeMotionEvent(
7475 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7476
7477 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7478 NotifyMotionArgs staleMotionUp =
7479 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7480 .displayId(ADISPLAY_ID_DEFAULT)
7481 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7482 .build();
7483 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7484 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7485 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7486 mDispatcher->notifyMotion(staleMotionUp);
7487
7488 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7489 // events, where we would cancel the current keys instead.
7490 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7491 windowInSecondary->assertNoEvents();
7492}
7493
Jackal Guof9696682018-10-05 12:23:23 +08007494class InputFilterTest : public InputDispatcherTest {
7495protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007496 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7497 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007498 NotifyMotionArgs motionArgs;
7499
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007500 motionArgs =
7501 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007502 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007503 motionArgs =
7504 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007505 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007506 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007507 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007508 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007509 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007510 } else {
7511 mFakePolicy->assertFilterInputEventWasNotCalled();
7512 }
7513 }
7514
7515 void testNotifyKey(bool expectToBeFiltered) {
7516 NotifyKeyArgs keyArgs;
7517
7518 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007519 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007520 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007521 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007522 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007523
7524 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007525 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007526 } else {
7527 mFakePolicy->assertFilterInputEventWasNotCalled();
7528 }
7529 }
7530};
7531
7532// Test InputFilter for MotionEvent
7533TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7534 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007535 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7536 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007537
7538 // Enable InputFilter
7539 mDispatcher->setInputFilterEnabled(true);
7540 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007541 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7542 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007543
7544 // Disable InputFilter
7545 mDispatcher->setInputFilterEnabled(false);
7546 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007547 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7548 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007549}
7550
7551// Test InputFilter for KeyEvent
7552TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7553 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007554 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007555
7556 // Enable InputFilter
7557 mDispatcher->setInputFilterEnabled(true);
7558 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007559 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007560
7561 // Disable InputFilter
7562 mDispatcher->setInputFilterEnabled(false);
7563 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007564 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007565}
7566
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007567// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7568// logical display coordinate space.
7569TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7570 ui::Transform firstDisplayTransform;
7571 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7572 ui::Transform secondDisplayTransform;
7573 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7574
7575 std::vector<gui::DisplayInfo> displayInfos(2);
7576 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7577 displayInfos[0].transform = firstDisplayTransform;
7578 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7579 displayInfos[1].transform = secondDisplayTransform;
7580
Patrick Williamsd828f302023-04-28 17:52:08 -05007581 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007582
7583 // Enable InputFilter
7584 mDispatcher->setInputFilterEnabled(true);
7585
7586 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007587 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7588 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007589}
7590
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007591class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7592protected:
7593 virtual void SetUp() override {
7594 InputDispatcherTest::SetUp();
7595
7596 /**
7597 * We don't need to enable input filter to test the injected event policy, but we enabled it
7598 * here to make the tests more realistic, since this policy only matters when inputfilter is
7599 * on.
7600 */
7601 mDispatcher->setInputFilterEnabled(true);
7602
7603 std::shared_ptr<InputApplicationHandle> application =
7604 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007605 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7606 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007607
7608 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7609 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007610 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007611 setFocusedWindow(mWindow);
7612 mWindow->consumeFocusEvent(true);
7613 }
7614
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007615 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7616 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007617 KeyEvent event;
7618
7619 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7620 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7621 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007622 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007623 const int32_t additionalPolicyFlags =
7624 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007626 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007627 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007628 policyFlags | additionalPolicyFlags));
7629
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007630 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007631 }
7632
7633 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7634 int32_t flags) {
7635 MotionEvent event;
7636 PointerProperties pointerProperties[1];
7637 PointerCoords pointerCoords[1];
7638 pointerProperties[0].clear();
7639 pointerProperties[0].id = 0;
7640 pointerCoords[0].clear();
7641 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7642 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7643
7644 ui::Transform identityTransform;
7645 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7646 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7647 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7648 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7649 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007650 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007651 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007652 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007653
7654 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007656 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007657 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007658 policyFlags | additionalPolicyFlags));
7659
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007660 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007661 }
7662
7663private:
7664 sp<FakeWindowHandle> mWindow;
7665};
7666
7667TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007668 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7669 // filter. Without it, the event will no different from a regularly injected event, and the
7670 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007671 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7672 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007673}
7674
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007675TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007676 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007677 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007678 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7679}
7680
7681TEST_F(InputFilterInjectionPolicyTest,
7682 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7683 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007684 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007685 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007686}
7687
7688TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007689 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7690 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007691}
7692
chaviwfd6d3512019-03-25 13:23:49 -07007693class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007694 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007695 InputDispatcherTest::SetUp();
7696
Chris Yea209fde2020-07-22 13:54:51 -07007697 std::shared_ptr<FakeApplicationHandle> application =
7698 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007699 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007700 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007701 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007702
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007703 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007704 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007705 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007706
7707 // Set focused application.
7708 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007709 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007710
7711 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007712 mDispatcher->onWindowInfosChanged(
7713 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007714 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007715 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007716 }
7717
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007718 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007719 InputDispatcherTest::TearDown();
7720
7721 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007722 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007723 }
7724
7725protected:
7726 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007727 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007728 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007729};
7730
7731// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7732// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7733// the onPointerDownOutsideFocus callback.
7734TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007736 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007737 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007739 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007740
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007741 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007742 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7743}
7744
7745// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7746// DOWN on the window that doesn't have focus. Ensure no window received the
7747// onPointerDownOutsideFocus callback.
7748TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007750 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7751 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007753 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007754
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007755 ASSERT_TRUE(mDispatcher->waitForIdle());
7756 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007757}
7758
7759// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7760// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7761TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007763 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007764 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007765 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007766
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007767 ASSERT_TRUE(mDispatcher->waitForIdle());
7768 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007769}
7770
7771// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7772// DOWN on the window that already has focus. Ensure no window received the
7773// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007774TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007776 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007777 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007779 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007780
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007781 ASSERT_TRUE(mDispatcher->waitForIdle());
7782 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007783}
7784
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007785// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7786// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7787TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7788 const MotionEvent event =
7789 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7790 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007791 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007792 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7793 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007795 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7796 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7797
7798 ASSERT_TRUE(mDispatcher->waitForIdle());
7799 mFakePolicy->assertOnPointerDownWasNotCalled();
7800 // Ensure that the unfocused window did not receive any FOCUS events.
7801 mUnfocusedWindow->assertNoEvents();
7802}
7803
chaviwaf87b3e2019-10-01 16:59:28 -07007804// These tests ensures we can send touch events to a single client when there are multiple input
7805// windows that point to the same client token.
7806class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7807 virtual void SetUp() override {
7808 InputDispatcherTest::SetUp();
7809
Chris Yea209fde2020-07-22 13:54:51 -07007810 std::shared_ptr<FakeApplicationHandle> application =
7811 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007812 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7813 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007814 mWindow1->setFrame(Rect(0, 0, 100, 100));
7815
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00007816 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007817 mWindow2->setFrame(Rect(100, 100, 200, 200));
7818
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007819 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007820 }
7821
7822protected:
7823 sp<FakeWindowHandle> mWindow1;
7824 sp<FakeWindowHandle> mWindow2;
7825
7826 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007827 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007828 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7829 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007830 }
7831
7832 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7833 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007834 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007835 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007836 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007837 ASSERT_NE(nullptr, motionEvent);
7838 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007839
7840 for (size_t i = 0; i < points.size(); i++) {
7841 float expectedX = points[i].x;
7842 float expectedY = points[i].y;
7843
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007844 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007845 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007846 << ", got " << motionEvent->getX(i);
7847 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007848 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007849 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007850 }
7851 }
chaviw9eaa22c2020-07-01 16:21:27 -07007852
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007853 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007854 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007855 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7856 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007857
7858 // Always consume from window1 since it's the window that has the InputReceiver
7859 consumeMotionEvent(mWindow1, action, expectedPoints);
7860 }
chaviwaf87b3e2019-10-01 16:59:28 -07007861};
7862
7863TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7864 // Touch Window 1
7865 PointF touchedPoint = {10, 10};
7866 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007867 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007868
7869 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007870 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007871
7872 // Touch Window 2
7873 touchedPoint = {150, 150};
7874 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007875 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007876}
7877
chaviw9eaa22c2020-07-01 16:21:27 -07007878TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7879 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007880 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007881 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007882
7883 // Touch Window 1
7884 PointF touchedPoint = {10, 10};
7885 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007886 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007887 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007888 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007889
7890 // Touch Window 2
7891 touchedPoint = {150, 150};
7892 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007893 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7894 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007895
chaviw9eaa22c2020-07-01 16:21:27 -07007896 // Update the transform so rotation is set
7897 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007898 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007899 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7900 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007901}
7902
chaviw9eaa22c2020-07-01 16:21:27 -07007903TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007904 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007905 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007906
7907 // Touch Window 1
7908 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7909 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007910 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007911
7912 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007913 touchedPoints.push_back(PointF{150, 150});
7914 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007915 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007916
chaviw9eaa22c2020-07-01 16:21:27 -07007917 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007918 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007919 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007920
chaviw9eaa22c2020-07-01 16:21:27 -07007921 // Update the transform so rotation is set for Window 2
7922 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007923 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007924 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007925 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007926}
7927
chaviw9eaa22c2020-07-01 16:21:27 -07007928TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007929 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007930 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007931
7932 // Touch Window 1
7933 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7934 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007935 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007936
7937 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007938 touchedPoints.push_back(PointF{150, 150});
7939 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007940
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007941 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007942
7943 // Move both windows
7944 touchedPoints = {{20, 20}, {175, 175}};
7945 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7946 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7947
chaviw9eaa22c2020-07-01 16:21:27 -07007948 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007949
chaviw9eaa22c2020-07-01 16:21:27 -07007950 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007951 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007952 expectedPoints.pop_back();
7953
7954 // Touch Window 2
7955 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007956 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007957 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007958 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007959
7960 // Move both windows
7961 touchedPoints = {{20, 20}, {175, 175}};
7962 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7963 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7964
7965 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007966}
7967
7968TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7969 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007970 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007971
7972 // Touch Window 1
7973 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7974 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007975 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007976
7977 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007978 touchedPoints.push_back(PointF{150, 150});
7979 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007980
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007981 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007982
7983 // Move both windows
7984 touchedPoints = {{20, 20}, {175, 175}};
7985 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7986 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7987
chaviw9eaa22c2020-07-01 16:21:27 -07007988 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007989}
7990
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007991/**
7992 * When one of the windows is slippery, the touch should not slip into the other window with the
7993 * same input channel.
7994 */
7995TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7996 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007997 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007998
7999 // Touch down in window 1
8000 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8001 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8002 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8003
8004 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8005 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8006 // getting generated.
8007 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8008 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8009
8010 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8011}
8012
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008013/**
8014 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8015 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8016 * that the pointer is hovering over may have a different transform.
8017 */
8018TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008019 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008020
8021 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8023 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8024 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008025 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8026 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008027 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8029 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8030 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008031 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
8032 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8033 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8034}
8035
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008036class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8037 virtual void SetUp() override {
8038 InputDispatcherTest::SetUp();
8039
Chris Yea209fde2020-07-22 13:54:51 -07008040 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008041 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008042 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8043 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008044 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008045 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008046 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008047
8048 // Set focused application.
8049 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8050
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008051 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008052 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008053 mWindow->consumeFocusEvent(true);
8054 }
8055
8056 virtual void TearDown() override {
8057 InputDispatcherTest::TearDown();
8058 mWindow.clear();
8059 }
8060
8061protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008062 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008063 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008064 sp<FakeWindowHandle> mWindow;
8065 static constexpr PointF WINDOW_LOCATION = {20, 20};
8066
8067 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008068 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8069 .x(WINDOW_LOCATION.x)
8070 .y(WINDOW_LOCATION.y);
8071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8072 .pointer(touchingPointer)
8073 .build());
8074 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8075 .pointer(touchingPointer)
8076 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008077 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008078
8079 sp<FakeWindowHandle> addSpyWindow() {
8080 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008081 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008082 spy->setTrustedOverlay(true);
8083 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008084 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008085 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008086 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008087 return spy;
8088 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008089};
8090
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008091// Send a tap and respond, which should not cause an ANR.
8092TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8093 tapOnWindow();
8094 mWindow->consumeMotionDown();
8095 mWindow->consumeMotionUp();
8096 ASSERT_TRUE(mDispatcher->waitForIdle());
8097 mFakePolicy->assertNotifyAnrWasNotCalled();
8098}
8099
8100// Send a regular key and respond, which should not cause an ANR.
8101TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008103 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8104 ASSERT_TRUE(mDispatcher->waitForIdle());
8105 mFakePolicy->assertNotifyAnrWasNotCalled();
8106}
8107
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008108TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8109 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008110 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008111 mWindow->consumeFocusEvent(false);
8112
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008113 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008114 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8115 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008116 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008118 // Key will not go to window because we have no focused window.
8119 // The 'no focused window' ANR timer should start instead.
8120
8121 // Now, the focused application goes away.
8122 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8123 // The key should get dropped and there should be no ANR.
8124
8125 ASSERT_TRUE(mDispatcher->waitForIdle());
8126 mFakePolicy->assertNotifyAnrWasNotCalled();
8127}
8128
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008129// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008130// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8131// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008132TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008134 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008135 WINDOW_LOCATION));
8136
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008137 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008138 ASSERT_TRUE(sequenceNum);
8139 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008140 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008141
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008142 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008143 mWindow->consumeMotionEvent(
8144 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008145 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008146 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008147}
8148
8149// Send a key to the app and have the app not respond right away.
8150TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8151 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008153 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008154 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008155 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008156 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008157 ASSERT_TRUE(mDispatcher->waitForIdle());
8158}
8159
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008160// We have a focused application, but no focused window
8161TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008162 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008163 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008164 mWindow->consumeFocusEvent(false);
8165
8166 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008168 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008169 WINDOW_LOCATION));
8170 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8171 mDispatcher->waitForIdle();
8172 mFakePolicy->assertNotifyAnrWasNotCalled();
8173
8174 // Once a focused event arrives, we get an ANR for this application
8175 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8176 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008177 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008178 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008179 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008180 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008181 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008182 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008183 ASSERT_TRUE(mDispatcher->waitForIdle());
8184}
8185
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008186/**
8187 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8188 * there will not be an ANR.
8189 */
8190TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8191 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008192 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008193 mWindow->consumeFocusEvent(false);
8194
8195 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008196 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8197 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008198 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8199 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8200
8201 // Define a valid key down event that is stale (too old).
8202 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008203 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008204 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008205
8206 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8207
8208 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008209 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008210 InputEventInjectionSync::WAIT_FOR_RESULT,
8211 INJECT_EVENT_TIMEOUT, policyFlags);
8212 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8213 << "Injection should fail because the event is stale";
8214
8215 ASSERT_TRUE(mDispatcher->waitForIdle());
8216 mFakePolicy->assertNotifyAnrWasNotCalled();
8217 mWindow->assertNoEvents();
8218}
8219
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008220// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008221// Make sure that we don't notify policy twice about the same ANR.
8222TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008223 const std::chrono::duration appTimeout = 400ms;
8224 mApplication->setDispatchingTimeout(appTimeout);
8225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8226
Vishnu Nair47074b82020-08-14 11:54:47 -07008227 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008228 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008229 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008230
8231 // Once a focused event arrives, we get an ANR for this application
8232 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8233 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008234 const std::chrono::duration eventInjectionTimeout = 100ms;
8235 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008236 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008237 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008238 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8239 /*allowKeyRepeat=*/false);
8240 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8241 << "result=" << ftl::enum_string(result);
8242 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8243 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8244 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8245 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008246
Vishnu Naire4df8752022-09-08 09:17:55 -07008247 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008248 // ANR should not be raised again. It is up to policy to do that if it desires.
8249 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008250
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008251 // If we now get a focused window, the ANR should stop, but the policy handles that via
8252 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008253 ASSERT_TRUE(mDispatcher->waitForIdle());
8254}
8255
8256// We have a focused application, but no focused window
8257TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008258 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008259 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008260 mWindow->consumeFocusEvent(false);
8261
8262 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008263 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008264
Vishnu Naire4df8752022-09-08 09:17:55 -07008265 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8266 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008267
8268 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008269 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008270 ASSERT_TRUE(mDispatcher->waitForIdle());
8271 mWindow->assertNoEvents();
8272}
8273
8274/**
8275 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8276 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8277 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8278 * the ANR mechanism should still work.
8279 *
8280 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8281 * DOWN event, while not responding on the second one.
8282 */
8283TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8284 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008285 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008286 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8287 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8288 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008289 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008290
8291 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008292 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008293 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8294 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8295 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008296 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008297
8298 // We have now sent down and up. Let's consume first event and then ANR on the second.
8299 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8300 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008301 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008302}
8303
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008304// A spy window can receive an ANR
8305TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8306 sp<FakeWindowHandle> spy = addSpyWindow();
8307
8308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008309 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008310 WINDOW_LOCATION));
8311 mWindow->consumeMotionDown();
8312
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008313 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008314 ASSERT_TRUE(sequenceNum);
8315 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008316 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008317
8318 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008319 spy->consumeMotionEvent(
8320 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008321 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008322 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008323}
8324
8325// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008326// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008327TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8328 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008329
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008331 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008332 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008334
8335 // Stuck on the ACTION_UP
8336 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008337 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008338
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008339 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008340 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008341 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8342 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008343
8344 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8345 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008346 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008347 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008348 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008349}
8350
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008351// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008352// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008353TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8354 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008355
8356 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008357 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8358 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008359
8360 mWindow->consumeMotionDown();
8361 // Stuck on the ACTION_UP
8362 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008363 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008364
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008365 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008366 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008367 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8368 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008369
8370 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8371 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008372 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008373 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008374 spy->assertNoEvents();
8375}
8376
8377TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008378 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008379
Prabir Pradhanfb549072023-10-05 19:17:36 +00008380 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008381
8382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008383 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008384 WINDOW_LOCATION));
8385
8386 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8387 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8388 ASSERT_TRUE(consumeSeq);
8389
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008390 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8391 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008392
8393 monitor.finishEvent(*consumeSeq);
8394 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8395
8396 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008397 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008398}
8399
8400// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8401// process events, you don't get an anr. When the window later becomes unresponsive again, you
8402// get an ANR again.
8403// 1. tap -> block on ACTION_UP -> receive ANR
8404// 2. consume all pending events (= queue becomes healthy again)
8405// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8406TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8407 tapOnWindow();
8408
8409 mWindow->consumeMotionDown();
8410 // Block on ACTION_UP
8411 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008412 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008413 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8414 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008415 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008416 mWindow->assertNoEvents();
8417
8418 tapOnWindow();
8419 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008420 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008421 mWindow->consumeMotionUp();
8422
8423 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008424 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008425 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008426 mWindow->assertNoEvents();
8427}
8428
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008429// If a connection remains unresponsive for a while, make sure policy is only notified once about
8430// it.
8431TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008433 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008434 WINDOW_LOCATION));
8435
8436 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008437 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008438 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008439 // 'notifyConnectionUnresponsive' should only be called once per connection
8440 mFakePolicy->assertNotifyAnrWasNotCalled();
8441 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008442 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008443 mWindow->consumeMotionEvent(
8444 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008445 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008446 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008447 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008448 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008449}
8450
8451/**
8452 * 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 -07008453 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008454 *
8455 * Warning!!!
8456 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8457 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008458 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008459 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8460 *
8461 * If that value changes, this test should also change.
8462 */
8463TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8464 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008465 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008466
8467 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008468 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008469 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008470 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008471 ASSERT_TRUE(upSequenceNum);
8472 // Don't finish the events yet, and send a key
8473 // Injection will "succeed" because we will eventually give up and send the key to the focused
8474 // window even if motions are still being processed. But because the injection timeout is short,
8475 // we will receive INJECTION_TIMED_OUT as the result.
8476
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008477 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008478 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8479 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008480 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008481 // Key will not be sent to the window, yet, because the window is still processing events
8482 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008483 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8484 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8485 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8486 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008487
8488 std::this_thread::sleep_for(500ms);
8489 // if we wait long enough though, dispatcher will give up, and still send the key
8490 // to the focused window, even though we have not yet finished the motion event
8491 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8492 mWindow->finishEvent(*downSequenceNum);
8493 mWindow->finishEvent(*upSequenceNum);
8494}
8495
8496/**
8497 * If a window is processing a motion event, and then a key event comes in, the key event should
8498 * not go to the focused window until the motion is processed.
8499 * If then a new motion comes in, then the pending key event should be going to the currently
8500 * focused window right away.
8501 */
8502TEST_F(InputDispatcherSingleWindowAnr,
8503 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8504 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008505 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008506
8507 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008508 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008509 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008510 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008511 ASSERT_TRUE(upSequenceNum);
8512 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008513 mDispatcher->notifyKey(
8514 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8515 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8516 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008517 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008518 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8519 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8520 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8521 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008522
8523 // Now tap down again. It should cause the pending key to go to the focused window right away.
8524 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008525 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8526 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008527 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8528 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008529 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8530 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008531 mWindow->assertNoEvents();
8532}
8533
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008534/**
8535 * Send an event to the app and have the app not respond right away.
8536 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8537 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8538 * At some point, the window becomes responsive again.
8539 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8540 */
8541TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8543 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8544 .build());
8545
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008546 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008547 ASSERT_TRUE(sequenceNum);
8548 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8549 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8550
8551 mWindow->finishEvent(*sequenceNum);
8552 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8553 ASSERT_TRUE(mDispatcher->waitForIdle());
8554 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8555
8556 // Now that the window is responsive, let's continue the gesture.
8557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8558 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8559 .build());
8560
8561 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8562 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8563 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8564 .build());
8565
8566 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8567 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8568 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8569 .build());
8570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8571 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8572 .build());
8573 // We already canceled this pointer, so the window shouldn't get any new events.
8574 mWindow->assertNoEvents();
8575
8576 // Start another one.
8577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8578 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8579 .build());
8580 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8581}
8582
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008583class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8584 virtual void SetUp() override {
8585 InputDispatcherTest::SetUp();
8586
Chris Yea209fde2020-07-22 13:54:51 -07008587 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008588 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008589 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8590 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008591 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008592 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008593 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008594
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008595 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8596 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008597 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008598 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008599
8600 // Set focused application.
8601 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008602 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008603
8604 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008605 mDispatcher->onWindowInfosChanged(
8606 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008607 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008608 mFocusedWindow->consumeFocusEvent(true);
8609 }
8610
8611 virtual void TearDown() override {
8612 InputDispatcherTest::TearDown();
8613
8614 mUnfocusedWindow.clear();
8615 mFocusedWindow.clear();
8616 }
8617
8618protected:
Chris Yea209fde2020-07-22 13:54:51 -07008619 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008620 sp<FakeWindowHandle> mUnfocusedWindow;
8621 sp<FakeWindowHandle> mFocusedWindow;
8622 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8623 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8624 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8625
8626 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8627
8628 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8629
8630private:
8631 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008633 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008634 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008636 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008637 location));
8638 }
8639};
8640
8641// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8642// should be ANR'd first.
8643TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008645 injectMotionEvent(*mDispatcher,
8646 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8647 AINPUT_SOURCE_TOUCHSCREEN)
8648 .pointer(PointerBuilder(0, ToolType::FINGER)
8649 .x(FOCUSED_WINDOW_LOCATION.x)
8650 .y(FOCUSED_WINDOW_LOCATION.y))
8651 .build()));
8652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8653 injectMotionEvent(*mDispatcher,
8654 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8655 AINPUT_SOURCE_TOUCHSCREEN)
8656 .pointer(PointerBuilder(0, ToolType::FINGER)
8657 .x(FOCUSED_WINDOW_LOCATION.x)
8658 .y(FOCUSED_WINDOW_LOCATION.y))
8659 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008660 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008661 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008662 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008663 // We consumed all events, so no ANR
8664 ASSERT_TRUE(mDispatcher->waitForIdle());
8665 mFakePolicy->assertNotifyAnrWasNotCalled();
8666
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008668 injectMotionEvent(*mDispatcher,
8669 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8670 AINPUT_SOURCE_TOUCHSCREEN)
8671 .pointer(PointerBuilder(0, ToolType::FINGER)
8672 .x(FOCUSED_WINDOW_LOCATION.x)
8673 .y(FOCUSED_WINDOW_LOCATION.y))
8674 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008675 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008676 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008677
8678 const std::chrono::duration timeout =
8679 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008680 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008681
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008682 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008683 mFocusedWindow->consumeMotionDown();
8684 // This cancel is generated because the connection was unresponsive
8685 mFocusedWindow->consumeMotionCancel();
8686 mFocusedWindow->assertNoEvents();
8687 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008688 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008689 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8690 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008691 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008692}
8693
8694// If we have 2 windows with identical timeouts that are both unresponsive,
8695// it doesn't matter which order they should have ANR.
8696// But we should receive ANR for both.
8697TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8698 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008699 mUnfocusedWindow->setDispatchingTimeout(
8700 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008701 mDispatcher->onWindowInfosChanged(
8702 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008703
8704 tapOnFocusedWindow();
8705 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008706 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008707 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8708 mFocusedWindow->getDispatchingTimeout(
8709 DISPATCHING_TIMEOUT)),
8710 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8711
8712 ASSERT_THAT(anrConnectionTokens,
8713 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8714 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008715
8716 ASSERT_TRUE(mDispatcher->waitForIdle());
8717 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008718
8719 mFocusedWindow->consumeMotionDown();
8720 mFocusedWindow->consumeMotionUp();
8721 mUnfocusedWindow->consumeMotionOutside();
8722
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008723 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8724 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008725
8726 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008727 ASSERT_THAT(responsiveTokens,
8728 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8729 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008730 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008731}
8732
8733// If a window is already not responding, the second tap on the same window should be ignored.
8734// We should also log an error to account for the dropped event (not tested here).
8735// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8736TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8737 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008738 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008739 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008740 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008741 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008742 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008743 ASSERT_TRUE(upEventSequenceNum);
8744 const std::chrono::duration timeout =
8745 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008746 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008747
8748 // Tap once again
8749 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008751 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008752 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008753 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008754 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008755 FOCUSED_WINDOW_LOCATION));
8756 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8757 // valid touch target
8758 mUnfocusedWindow->assertNoEvents();
8759
8760 // Consume the first tap
8761 mFocusedWindow->finishEvent(*downEventSequenceNum);
8762 mFocusedWindow->finishEvent(*upEventSequenceNum);
8763 ASSERT_TRUE(mDispatcher->waitForIdle());
8764 // The second tap did not go to the focused window
8765 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008766 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008767 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8768 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008769 mFakePolicy->assertNotifyAnrWasNotCalled();
8770}
8771
8772// If you tap outside of all windows, there will not be ANR
8773TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008776 LOCATION_OUTSIDE_ALL_WINDOWS));
8777 ASSERT_TRUE(mDispatcher->waitForIdle());
8778 mFakePolicy->assertNotifyAnrWasNotCalled();
8779}
8780
8781// Since the focused window is paused, tapping on it should not produce any events
8782TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8783 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008784 mDispatcher->onWindowInfosChanged(
8785 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008786
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008787 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008788 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008789 FOCUSED_WINDOW_LOCATION));
8790
8791 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8792 ASSERT_TRUE(mDispatcher->waitForIdle());
8793 // Should not ANR because the window is paused, and touches shouldn't go to it
8794 mFakePolicy->assertNotifyAnrWasNotCalled();
8795
8796 mFocusedWindow->assertNoEvents();
8797 mUnfocusedWindow->assertNoEvents();
8798}
8799
8800/**
8801 * 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 -07008802 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008803 * If a different window becomes focused at this time, the key should go to that window instead.
8804 *
8805 * Warning!!!
8806 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8807 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008808 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008809 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8810 *
8811 * If that value changes, this test should also change.
8812 */
8813TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8814 // Set a long ANR timeout to prevent it from triggering
8815 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged(
8817 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008818
8819 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008820 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008821 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008822 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008823 ASSERT_TRUE(upSequenceNum);
8824 // Don't finish the events yet, and send a key
8825 // Injection will succeed because we will eventually give up and send the key to the focused
8826 // window even if motions are still being processed.
8827
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008828 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008829 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8830 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008832 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008833 // and the key remains pending, waiting for the touch events to be processed.
8834 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8835 // under the hood.
8836 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8837 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008838
8839 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008840 mFocusedWindow->setFocusable(false);
8841 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008842 mDispatcher->onWindowInfosChanged(
8843 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008844 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008845
8846 // Focus events should precede the key events
8847 mUnfocusedWindow->consumeFocusEvent(true);
8848 mFocusedWindow->consumeFocusEvent(false);
8849
8850 // Finish the tap events, which should unblock dispatcher
8851 mUnfocusedWindow->finishEvent(*downSequenceNum);
8852 mUnfocusedWindow->finishEvent(*upSequenceNum);
8853
8854 // Now that all queues are cleared and no backlog in the connections, the key event
8855 // can finally go to the newly focused "mUnfocusedWindow".
8856 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8857 mFocusedWindow->assertNoEvents();
8858 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008859 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008860}
8861
8862// When the touch stream is split across 2 windows, and one of them does not respond,
8863// then ANR should be raised and the touch should be canceled for the unresponsive window.
8864// The other window should not be affected by that.
8865TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8866 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008867 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8868 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8869 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008870 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008871
8872 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008873 mDispatcher->notifyMotion(
8874 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8875 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008876
8877 const std::chrono::duration timeout =
8878 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008879 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008880
8881 mUnfocusedWindow->consumeMotionDown();
8882 mFocusedWindow->consumeMotionDown();
8883 // Focused window may or may not receive ACTION_MOVE
8884 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008885 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008886 ASSERT_TRUE(moveOrCancelSequenceNum);
8887 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8888 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008889 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008890 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8891 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8892 mFocusedWindow->consumeMotionCancel();
8893 } else {
8894 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8895 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008896 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008897 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8898 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008899
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008900 mUnfocusedWindow->assertNoEvents();
8901 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008902 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008903}
8904
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008905/**
8906 * If we have no focused window, and a key comes in, we start the ANR timer.
8907 * The focused application should add a focused window before the timer runs out to prevent ANR.
8908 *
8909 * If the user touches another application during this time, the key should be dropped.
8910 * Next, if a new focused window comes in, without toggling the focused application,
8911 * then no ANR should occur.
8912 *
8913 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8914 * but in some cases the policy may not update the focused application.
8915 */
8916TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8917 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8918 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008919 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008920 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8921 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8922 mFocusedWindow->setFocusable(false);
8923
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008924 mDispatcher->onWindowInfosChanged(
8925 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008926 mFocusedWindow->consumeFocusEvent(false);
8927
8928 // Send a key. The ANR timer should start because there is no focused window.
8929 // 'focusedApplication' will get blamed if this timer completes.
8930 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008931 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008932 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8933 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008934 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008936
8937 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8938 // then the injected touches won't cause the focused event to get dropped.
8939 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8940 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8941 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8942 // For this test, it means that the key would get delivered to the window once it becomes
8943 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008944 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008945
8946 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008947 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8948 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8949 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008950
8951 // We do not consume the motion right away, because that would require dispatcher to first
8952 // process (== drop) the key event, and by that time, ANR will be raised.
8953 // Set the focused window first.
8954 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008955 mDispatcher->onWindowInfosChanged(
8956 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008957 setFocusedWindow(mFocusedWindow);
8958 mFocusedWindow->consumeFocusEvent(true);
8959 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8960 // to another application. This could be a bug / behaviour in the policy.
8961
8962 mUnfocusedWindow->consumeMotionDown();
8963
8964 ASSERT_TRUE(mDispatcher->waitForIdle());
8965 // Should not ANR because we actually have a focused window. It was just added too slowly.
8966 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8967}
8968
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08008969/**
8970 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
8971 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
8972 * dispatcher doesn't prune pointer events incorrectly.
8973 *
8974 * This test reproduces a crash in InputDispatcher.
8975 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
8976 *
8977 * Keep the currently focused application (mApplication), and have no focused window.
8978 * We set up two additional windows:
8979 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
8980 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
8981 * window. This window is not focusable, but is touchable.
8982 *
8983 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
8984 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
8985 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
8986 *
8987 * Now, we touch "Another window". This window is owned by a different application than
8988 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
8989 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
8990 * dropping the events from its queue. Ensure that no crash occurs.
8991 *
8992 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
8993 * This does not affect the test running time.
8994 */
8995TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
8996 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
8997 std::make_shared<FakeApplicationHandle>();
8998 systemUiApplication->setDispatchingTimeout(3000ms);
8999 mFakePolicy->setStaleEventTimeout(3000ms);
9000 sp<FakeWindowHandle> navigationBar =
9001 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9002 ADISPLAY_ID_DEFAULT);
9003 navigationBar->setFocusable(false);
9004 navigationBar->setWatchOutsideTouch(true);
9005 navigationBar->setFrame(Rect(0, 0, 100, 100));
9006
9007 mApplication->setDispatchingTimeout(3000ms);
9008 // 'mApplication' is already focused, but we call it again here to make it explicit.
9009 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9010
9011 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9012 std::make_shared<FakeApplicationHandle>();
9013 sp<FakeWindowHandle> appWindow =
9014 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9015 ADISPLAY_ID_DEFAULT);
9016 appWindow->setFocusable(false);
9017 appWindow->setFrame(Rect(100, 100, 200, 200));
9018
9019 mDispatcher->onWindowInfosChanged(
9020 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9021 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9022 mFocusedWindow->consumeFocusEvent(false);
9023
9024 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9025 // in response.
9026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9027 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9028 .build());
9029 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9030
9031 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9032 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9033 InputEventInjectionResult result =
9034 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9035 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9036 /*allowKeyRepeat=*/false);
9037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9038
9039 // Finish the gesture - lift up finger and inject ACTION_UP key event
9040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9041 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9042 .build());
9043 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9044 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9045 /*allowKeyRepeat=*/false);
9046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9047 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9048 // getting any events yet.
9049 navigationBar->assertNoEvents();
9050
9051 // Now touch "Another window". This touch is going to a different application than the one we
9052 // are waiting for (which is 'mApplication').
9053 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9054 // trying to be injected) and to continue processing the rest of the events in the original
9055 // order.
9056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9057 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9058 .build());
9059 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9060 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9061 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9062
9063 appWindow->assertNoEvents();
9064 navigationBar->assertNoEvents();
9065}
9066
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009067// These tests ensure we cannot send touch events to a window that's positioned behind a window
9068// that has feature NO_INPUT_CHANNEL.
9069// Layout:
9070// Top (closest to user)
9071// mNoInputWindow (above all windows)
9072// mBottomWindow
9073// Bottom (furthest from user)
9074class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9075 virtual void SetUp() override {
9076 InputDispatcherTest::SetUp();
9077
9078 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009079 mNoInputWindow =
9080 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9081 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009082 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009083 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009084 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9085 // It's perfectly valid for this window to not have an associated input channel
9086
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009087 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9088 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009089 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9090
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009091 mDispatcher->onWindowInfosChanged(
9092 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009093 }
9094
9095protected:
9096 std::shared_ptr<FakeApplicationHandle> mApplication;
9097 sp<FakeWindowHandle> mNoInputWindow;
9098 sp<FakeWindowHandle> mBottomWindow;
9099};
9100
9101TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9102 PointF touchedPoint = {10, 10};
9103
Prabir Pradhan678438e2023-04-13 19:32:51 +00009104 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9105 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9106 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009107
9108 mNoInputWindow->assertNoEvents();
9109 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9110 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9111 // and therefore should prevent mBottomWindow from receiving touches
9112 mBottomWindow->assertNoEvents();
9113}
9114
9115/**
9116 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9117 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9118 */
9119TEST_F(InputDispatcherMultiWindowOcclusionTests,
9120 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009121 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9122 "Window with input channel and NO_INPUT_CHANNEL",
9123 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009124
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009125 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009126 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009127 mDispatcher->onWindowInfosChanged(
9128 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009129
9130 PointF touchedPoint = {10, 10};
9131
Prabir Pradhan678438e2023-04-13 19:32:51 +00009132 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9133 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9134 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009135
9136 mNoInputWindow->assertNoEvents();
9137 mBottomWindow->assertNoEvents();
9138}
9139
Vishnu Nair958da932020-08-21 17:12:37 -07009140class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9141protected:
9142 std::shared_ptr<FakeApplicationHandle> mApp;
9143 sp<FakeWindowHandle> mWindow;
9144 sp<FakeWindowHandle> mMirror;
9145
9146 virtual void SetUp() override {
9147 InputDispatcherTest::SetUp();
9148 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009149 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009150 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009151 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9152 mWindow->setFocusable(true);
9153 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009154 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009155 }
9156};
9157
9158TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9159 // Request focus on a mirrored window
9160 setFocusedWindow(mMirror);
9161
9162 // window gets focused
9163 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009165 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009166 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9167}
9168
9169// A focused & mirrored window remains focused only if the window and its mirror are both
9170// focusable.
9171TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9172 setFocusedWindow(mMirror);
9173
9174 // window gets focused
9175 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009177 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009178 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009180 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009181 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9182
9183 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009184 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009185
9186 // window loses focus since one of the windows associated with the token in not focusable
9187 mWindow->consumeFocusEvent(false);
9188
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009189 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009190 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009191 mWindow->assertNoEvents();
9192}
9193
9194// A focused & mirrored window remains focused until the window and its mirror both become
9195// invisible.
9196TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9197 setFocusedWindow(mMirror);
9198
9199 // window gets focused
9200 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009202 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009203 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009205 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009206 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9207
9208 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009209 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009210
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009212 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009213 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009215 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009216 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9217
9218 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009219 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009220
9221 // window loses focus only after all windows associated with the token become invisible.
9222 mWindow->consumeFocusEvent(false);
9223
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009224 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009225 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009226 mWindow->assertNoEvents();
9227}
9228
9229// A focused & mirrored window remains focused until both windows are removed.
9230TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9231 setFocusedWindow(mMirror);
9232
9233 // window gets focused
9234 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009236 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009237 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009239 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009240 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9241
9242 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009243 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009244
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009246 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009247 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009249 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009250 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9251
9252 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009253 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009254 mWindow->consumeFocusEvent(false);
9255
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009256 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009257 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009258 mWindow->assertNoEvents();
9259}
9260
9261// Focus request can be pending until one window becomes visible.
9262TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9263 // Request focus on an invisible mirror.
9264 mWindow->setVisible(false);
9265 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009266 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009267 setFocusedWindow(mMirror);
9268
9269 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009271 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9272 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009273
9274 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009275 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009276
9277 // window gets focused
9278 mWindow->consumeFocusEvent(true);
9279 // window gets the pending key event
9280 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9281}
Prabir Pradhan99987712020-11-10 18:43:05 -08009282
9283class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9284protected:
9285 std::shared_ptr<FakeApplicationHandle> mApp;
9286 sp<FakeWindowHandle> mWindow;
9287 sp<FakeWindowHandle> mSecondWindow;
9288
9289 void SetUp() override {
9290 InputDispatcherTest::SetUp();
9291 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009292 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009293 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009294 mSecondWindow =
9295 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009296 mSecondWindow->setFocusable(true);
9297
9298 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009299 mDispatcher->onWindowInfosChanged(
9300 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009301
9302 setFocusedWindow(mWindow);
9303 mWindow->consumeFocusEvent(true);
9304 }
9305
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009306 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009307 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009308 }
9309
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009310 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9311 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009312 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009313 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9314 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009315 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009316 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009317 }
9318};
9319
9320TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9321 // Ensure that capture cannot be obtained for unfocused windows.
9322 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9323 mFakePolicy->assertSetPointerCaptureNotCalled();
9324 mSecondWindow->assertNoEvents();
9325
9326 // Ensure that capture can be enabled from the focus window.
9327 requestAndVerifyPointerCapture(mWindow, true);
9328
9329 // Ensure that capture cannot be disabled from a window that does not have capture.
9330 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9331 mFakePolicy->assertSetPointerCaptureNotCalled();
9332
9333 // Ensure that capture can be disabled from the window with capture.
9334 requestAndVerifyPointerCapture(mWindow, false);
9335}
9336
9337TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009338 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009339
9340 setFocusedWindow(mSecondWindow);
9341
9342 // Ensure that the capture disabled event was sent first.
9343 mWindow->consumeCaptureEvent(false);
9344 mWindow->consumeFocusEvent(false);
9345 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009346 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009347
9348 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009349 notifyPointerCaptureChanged({});
9350 notifyPointerCaptureChanged(request);
9351 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009352 mWindow->assertNoEvents();
9353 mSecondWindow->assertNoEvents();
9354 mFakePolicy->assertSetPointerCaptureNotCalled();
9355}
9356
9357TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009358 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009359
9360 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009361 notifyPointerCaptureChanged({});
9362 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009363
9364 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009365 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009366 mWindow->consumeCaptureEvent(false);
9367 mWindow->assertNoEvents();
9368}
9369
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009370TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9371 requestAndVerifyPointerCapture(mWindow, true);
9372
9373 // The first window loses focus.
9374 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009375 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009376 mWindow->consumeCaptureEvent(false);
9377
9378 // Request Pointer Capture from the second window before the notification from InputReader
9379 // arrives.
9380 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009381 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009382
9383 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009384 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009385
9386 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009387 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009388
9389 mSecondWindow->consumeFocusEvent(true);
9390 mSecondWindow->consumeCaptureEvent(true);
9391}
9392
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009393TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9394 // App repeatedly enables and disables capture.
9395 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9396 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9397 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9398 mFakePolicy->assertSetPointerCaptureCalled(false);
9399 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9400 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9401
9402 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9403 // first request is now stale, this should do nothing.
9404 notifyPointerCaptureChanged(firstRequest);
9405 mWindow->assertNoEvents();
9406
9407 // InputReader notifies that the second request was enabled.
9408 notifyPointerCaptureChanged(secondRequest);
9409 mWindow->consumeCaptureEvent(true);
9410}
9411
Prabir Pradhan7092e262022-05-03 16:51:09 +00009412TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9413 requestAndVerifyPointerCapture(mWindow, true);
9414
9415 // App toggles pointer capture off and on.
9416 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9417 mFakePolicy->assertSetPointerCaptureCalled(false);
9418
9419 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9420 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9421
9422 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9423 // preceding "disable" request.
9424 notifyPointerCaptureChanged(enableRequest);
9425
9426 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9427 // any notifications.
9428 mWindow->assertNoEvents();
9429}
9430
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009431/**
9432 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9433 * mouse movements don't affect the previous mouse hovering state.
9434 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9435 * HOVER_MOVE events).
9436 */
9437TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9438 // Mouse hover on the window
9439 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9440 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9441 .build());
9442 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9443 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9444 .build());
9445
9446 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9447 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9448
9449 // Start pointer capture
9450 requestAndVerifyPointerCapture(mWindow, true);
9451
9452 // Send some relative mouse movements and receive them in the window.
9453 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9454 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9455 .build());
9456 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9457 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9458
9459 // Stop pointer capture
9460 requestAndVerifyPointerCapture(mWindow, false);
9461
9462 // Continue hovering on the window
9463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9464 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9465 .build());
9466 mWindow->consumeMotionEvent(
9467 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9468
9469 mWindow->assertNoEvents();
9470}
9471
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009472class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9473protected:
9474 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009475
9476 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9477 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9478
9479 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9480 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9481
9482 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9483 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9484 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9485 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9486 MAXIMUM_OBSCURING_OPACITY);
9487
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009488 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9489 static constexpr gui::Uid APP_B_UID{10002};
9490 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009491
9492 sp<FakeWindowHandle> mTouchWindow;
9493
9494 virtual void SetUp() override {
9495 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009496 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009497 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9498 }
9499
9500 virtual void TearDown() override {
9501 InputDispatcherTest::TearDown();
9502 mTouchWindow.clear();
9503 }
9504
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009505 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009506 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009507 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009508 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009509 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009510 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009511 return window;
9512 }
9513
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009514 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009515 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9516 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009517 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009518 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009519 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009520 return window;
9521 }
9522
9523 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009524 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9525 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9526 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009527 }
9528};
9529
9530TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009531 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009532 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009533 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009534
9535 touch();
9536
9537 mTouchWindow->assertNoEvents();
9538}
9539
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009540TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009541 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9542 const sp<FakeWindowHandle>& w =
9543 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009544 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009545
9546 touch();
9547
9548 mTouchWindow->assertNoEvents();
9549}
9550
9551TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009552 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9553 const sp<FakeWindowHandle>& w =
9554 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009555 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009556
9557 touch();
9558
9559 w->assertNoEvents();
9560}
9561
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009562TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009563 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009564 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009565
9566 touch();
9567
9568 mTouchWindow->consumeAnyMotionDown();
9569}
9570
9571TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009572 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009573 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009574 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009575 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009576
9577 touch({PointF{100, 100}});
9578
9579 mTouchWindow->consumeAnyMotionDown();
9580}
9581
9582TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009583 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009584 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009585 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009586
9587 touch();
9588
9589 mTouchWindow->consumeAnyMotionDown();
9590}
9591
9592TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9593 const sp<FakeWindowHandle>& w =
9594 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009595 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009596
9597 touch();
9598
9599 mTouchWindow->consumeAnyMotionDown();
9600}
9601
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009602TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9603 const sp<FakeWindowHandle>& w =
9604 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009605 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009606
9607 touch();
9608
9609 w->assertNoEvents();
9610}
9611
9612/**
9613 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9614 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9615 * window, the occluding window will still receive ACTION_OUTSIDE event.
9616 */
9617TEST_F(InputDispatcherUntrustedTouchesTest,
9618 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9619 const sp<FakeWindowHandle>& w =
9620 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009621 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009622 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009623
9624 touch();
9625
9626 w->consumeMotionOutside();
9627}
9628
9629TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9630 const sp<FakeWindowHandle>& w =
9631 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009632 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009633 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009634
9635 touch();
9636
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009637 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009638}
9639
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009640TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009641 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009642 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9643 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009644 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009645
9646 touch();
9647
9648 mTouchWindow->consumeAnyMotionDown();
9649}
9650
9651TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9652 const sp<FakeWindowHandle>& w =
9653 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9654 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009655 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009656
9657 touch();
9658
9659 mTouchWindow->consumeAnyMotionDown();
9660}
9661
9662TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009663 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009664 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9665 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009666 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009667
9668 touch();
9669
9670 mTouchWindow->assertNoEvents();
9671}
9672
9673TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9674 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9675 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009676 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9677 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009678 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009679 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9680 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009681 mDispatcher->onWindowInfosChanged(
9682 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009683
9684 touch();
9685
9686 mTouchWindow->assertNoEvents();
9687}
9688
9689TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9690 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9691 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009692 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9693 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009694 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009695 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9696 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009697 mDispatcher->onWindowInfosChanged(
9698 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009699
9700 touch();
9701
9702 mTouchWindow->consumeAnyMotionDown();
9703}
9704
9705TEST_F(InputDispatcherUntrustedTouchesTest,
9706 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9707 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009708 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9709 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009710 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009711 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9712 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009713 mDispatcher->onWindowInfosChanged(
9714 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009715
9716 touch();
9717
9718 mTouchWindow->consumeAnyMotionDown();
9719}
9720
9721TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9722 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009723 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9724 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009725 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009726 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9727 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009728 mDispatcher->onWindowInfosChanged(
9729 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009730
9731 touch();
9732
9733 mTouchWindow->assertNoEvents();
9734}
9735
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009736TEST_F(InputDispatcherUntrustedTouchesTest,
9737 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9738 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009739 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9740 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009741 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009742 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9743 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009744 mDispatcher->onWindowInfosChanged(
9745 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009746
9747 touch();
9748
9749 mTouchWindow->assertNoEvents();
9750}
9751
9752TEST_F(InputDispatcherUntrustedTouchesTest,
9753 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9754 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009755 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9756 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009757 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009758 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9759 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009760 mDispatcher->onWindowInfosChanged(
9761 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009762
9763 touch();
9764
9765 mTouchWindow->consumeAnyMotionDown();
9766}
9767
9768TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9769 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009770 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9771 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009772 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009773
9774 touch();
9775
9776 mTouchWindow->consumeAnyMotionDown();
9777}
9778
9779TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9780 const sp<FakeWindowHandle>& w =
9781 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009782 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009783
9784 touch();
9785
9786 mTouchWindow->consumeAnyMotionDown();
9787}
9788
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009789TEST_F(InputDispatcherUntrustedTouchesTest,
9790 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9791 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9792 const sp<FakeWindowHandle>& w =
9793 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009794 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009795
9796 touch();
9797
9798 mTouchWindow->assertNoEvents();
9799}
9800
9801TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9802 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9803 const sp<FakeWindowHandle>& w =
9804 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009805 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009806
9807 touch();
9808
9809 mTouchWindow->consumeAnyMotionDown();
9810}
9811
9812TEST_F(InputDispatcherUntrustedTouchesTest,
9813 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9814 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9815 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009816 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9817 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009818 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009819
9820 touch();
9821
9822 mTouchWindow->consumeAnyMotionDown();
9823}
9824
9825TEST_F(InputDispatcherUntrustedTouchesTest,
9826 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9827 const sp<FakeWindowHandle>& w1 =
9828 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9829 OPACITY_BELOW_THRESHOLD);
9830 const sp<FakeWindowHandle>& w2 =
9831 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9832 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009833 mDispatcher->onWindowInfosChanged(
9834 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009835
9836 touch();
9837
9838 mTouchWindow->assertNoEvents();
9839}
9840
9841/**
9842 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9843 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9844 * (which alone would result in allowing touches) does not affect the blocking behavior.
9845 */
9846TEST_F(InputDispatcherUntrustedTouchesTest,
9847 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9848 const sp<FakeWindowHandle>& wB =
9849 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9850 OPACITY_BELOW_THRESHOLD);
9851 const sp<FakeWindowHandle>& wC =
9852 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9853 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009854 mDispatcher->onWindowInfosChanged(
9855 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009856
9857 touch();
9858
9859 mTouchWindow->assertNoEvents();
9860}
9861
9862/**
9863 * This test is testing that a window from a different UID but with same application token doesn't
9864 * block the touch. Apps can share the application token for close UI collaboration for example.
9865 */
9866TEST_F(InputDispatcherUntrustedTouchesTest,
9867 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9868 const sp<FakeWindowHandle>& w =
9869 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9870 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009871 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009872
9873 touch();
9874
9875 mTouchWindow->consumeAnyMotionDown();
9876}
9877
arthurhungb89ccb02020-12-30 16:19:01 +08009878class InputDispatcherDragTests : public InputDispatcherTest {
9879protected:
9880 std::shared_ptr<FakeApplicationHandle> mApp;
9881 sp<FakeWindowHandle> mWindow;
9882 sp<FakeWindowHandle> mSecondWindow;
9883 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009884 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009885 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9886 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009887
9888 void SetUp() override {
9889 InputDispatcherTest::SetUp();
9890 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009891 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009892 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009893
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009894 mSecondWindow =
9895 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009896 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009897
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009898 mSpyWindow =
9899 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009900 mSpyWindow->setSpy(true);
9901 mSpyWindow->setTrustedOverlay(true);
9902 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9903
arthurhungb89ccb02020-12-30 16:19:01 +08009904 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009905 mDispatcher->onWindowInfosChanged(
9906 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9907 {},
9908 0,
9909 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009910 }
9911
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009912 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9913 switch (fromSource) {
9914 case AINPUT_SOURCE_TOUCHSCREEN:
9915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009916 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009917 ADISPLAY_ID_DEFAULT, {50, 50}))
9918 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9919 break;
9920 case AINPUT_SOURCE_STYLUS:
9921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009922 injectMotionEvent(*mDispatcher,
9923 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9924 AINPUT_SOURCE_STYLUS)
9925 .buttonState(
9926 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9927 .pointer(PointerBuilder(0, ToolType::STYLUS)
9928 .x(50)
9929 .y(50))
9930 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009931 break;
9932 case AINPUT_SOURCE_MOUSE:
9933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009934 injectMotionEvent(*mDispatcher,
9935 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9936 AINPUT_SOURCE_MOUSE)
9937 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9938 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9939 ToolType::MOUSE)
9940 .x(50)
9941 .y(50))
9942 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009943 break;
9944 default:
9945 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9946 }
arthurhungb89ccb02020-12-30 16:19:01 +08009947
9948 // Window should receive motion event.
9949 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009950 // Spy window should also receive motion event
9951 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009952 }
9953
9954 // Start performing drag, we will create a drag window and transfer touch to it.
9955 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9956 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009957 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009958 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009959 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009960 }
arthurhungb89ccb02020-12-30 16:19:01 +08009961
9962 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009963 mDragWindow =
9964 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009965 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009966 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9967 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9968 {},
9969 0,
9970 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009971
9972 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009973 bool transferred =
9974 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009975 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009976 if (transferred) {
9977 mWindow->consumeMotionCancel();
9978 mDragWindow->consumeMotionDown();
9979 }
9980 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009981 }
9982};
9983
9984TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009985 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009986
9987 // Move on window.
9988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009989 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009990 ADISPLAY_ID_DEFAULT, {50, 50}))
9991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9992 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9993 mWindow->consumeDragEvent(false, 50, 50);
9994 mSecondWindow->assertNoEvents();
9995
9996 // Move to another window.
9997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009998 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009999 ADISPLAY_ID_DEFAULT, {150, 50}))
10000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10001 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10002 mWindow->consumeDragEvent(true, 150, 50);
10003 mSecondWindow->consumeDragEvent(false, 50, 50);
10004
10005 // Move back to original window.
10006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010007 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010008 ADISPLAY_ID_DEFAULT, {50, 50}))
10009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10010 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10011 mWindow->consumeDragEvent(false, 50, 50);
10012 mSecondWindow->consumeDragEvent(true, -50, 50);
10013
10014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010015 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10016 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10018 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10019 mWindow->assertNoEvents();
10020 mSecondWindow->assertNoEvents();
10021}
10022
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010023TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010024 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010025
10026 // No cancel event after drag start
10027 mSpyWindow->assertNoEvents();
10028
10029 const MotionEvent secondFingerDownEvent =
10030 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10031 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010032 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10033 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010034 .build();
10035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010036 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010037 InputEventInjectionSync::WAIT_FOR_RESULT))
10038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10039
10040 // Receives cancel for first pointer after next pointer down
10041 mSpyWindow->consumeMotionCancel();
10042 mSpyWindow->consumeMotionDown();
10043
10044 mSpyWindow->assertNoEvents();
10045}
10046
arthurhungf452d0b2021-01-06 00:19:52 +080010047TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010048 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010049
10050 // Move on window.
10051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010052 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010053 ADISPLAY_ID_DEFAULT, {50, 50}))
10054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10055 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10056 mWindow->consumeDragEvent(false, 50, 50);
10057 mSecondWindow->assertNoEvents();
10058
10059 // Move to another window.
10060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010061 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010062 ADISPLAY_ID_DEFAULT, {150, 50}))
10063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10064 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10065 mWindow->consumeDragEvent(true, 150, 50);
10066 mSecondWindow->consumeDragEvent(false, 50, 50);
10067
10068 // drop to another window.
10069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010070 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010071 {150, 50}))
10072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10073 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010074 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010075 mWindow->assertNoEvents();
10076 mSecondWindow->assertNoEvents();
10077}
10078
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010079TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10080 startDrag();
10081
10082 // No cancel event after drag start
10083 mSpyWindow->assertNoEvents();
10084
10085 const MotionEvent secondFingerDownEvent =
10086 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10087 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10088 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10089 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10090 .build();
10091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10092 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10093 InputEventInjectionSync::WAIT_FOR_RESULT))
10094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10095
10096 // Receives cancel for first pointer after next pointer down
10097 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010098 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010099 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10100
10101 mSpyWindow->assertNoEvents();
10102
10103 // Spy window calls pilfer pointers
10104 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10105 mDragWindow->assertNoEvents();
10106
10107 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010108 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010109 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10110 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10111 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10112 .build();
10113 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010114 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010115 InputEventInjectionSync::WAIT_FOR_RESULT))
10116 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10117
10118 // Drag window should still receive the new event
10119 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10120 mDragWindow->assertNoEvents();
10121}
10122
arthurhung6d4bed92021-03-17 11:59:33 +080010123TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010124 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010125
10126 // Move on window and keep button pressed.
10127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010128 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010129 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10130 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010131 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010132 .build()))
10133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10134 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10135 mWindow->consumeDragEvent(false, 50, 50);
10136 mSecondWindow->assertNoEvents();
10137
10138 // Move to another window and release button, expect to drop item.
10139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010140 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010141 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10142 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010143 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010144 .build()))
10145 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10146 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10147 mWindow->assertNoEvents();
10148 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010149 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010150
10151 // nothing to the window.
10152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010153 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010154 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10155 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010156 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010157 .build()))
10158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10159 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10160 mWindow->assertNoEvents();
10161 mSecondWindow->assertNoEvents();
10162}
10163
Arthur Hung54745652022-04-20 07:17:41 +000010164TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010165 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010166
10167 // Set second window invisible.
10168 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010169 mDispatcher->onWindowInfosChanged(
10170 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010171
10172 // Move on window.
10173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010174 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010175 ADISPLAY_ID_DEFAULT, {50, 50}))
10176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10177 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10178 mWindow->consumeDragEvent(false, 50, 50);
10179 mSecondWindow->assertNoEvents();
10180
10181 // Move to another window.
10182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010183 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010184 ADISPLAY_ID_DEFAULT, {150, 50}))
10185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10186 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10187 mWindow->consumeDragEvent(true, 150, 50);
10188 mSecondWindow->assertNoEvents();
10189
10190 // drop to another window.
10191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010192 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010193 {150, 50}))
10194 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10195 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010196 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010197 mWindow->assertNoEvents();
10198 mSecondWindow->assertNoEvents();
10199}
10200
Arthur Hung54745652022-04-20 07:17:41 +000010201TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010202 // Ensure window could track pointerIds if it didn't support split touch.
10203 mWindow->setPreventSplitting(true);
10204
Arthur Hung54745652022-04-20 07:17:41 +000010205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010206 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010207 {50, 50}))
10208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10209 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10210
10211 const MotionEvent secondFingerDownEvent =
10212 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10213 .displayId(ADISPLAY_ID_DEFAULT)
10214 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010215 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10216 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010217 .build();
10218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010219 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010220 InputEventInjectionSync::WAIT_FOR_RESULT))
10221 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010222 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010223
10224 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010225 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010226}
10227
10228TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10229 // First down on second window.
10230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010231 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010232 {150, 50}))
10233 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10234
10235 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10236
10237 // Second down on first window.
10238 const MotionEvent secondFingerDownEvent =
10239 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10240 .displayId(ADISPLAY_ID_DEFAULT)
10241 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010242 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10243 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010244 .build();
10245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010246 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010247 InputEventInjectionSync::WAIT_FOR_RESULT))
10248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10249 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10250
10251 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010252 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010253
10254 // Move on window.
10255 const MotionEvent secondFingerMoveEvent =
10256 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10257 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010258 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10259 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010260 .build();
10261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010262 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010263 InputEventInjectionSync::WAIT_FOR_RESULT));
10264 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10265 mWindow->consumeDragEvent(false, 50, 50);
10266 mSecondWindow->consumeMotionMove();
10267
10268 // Release the drag pointer should perform drop.
10269 const MotionEvent secondFingerUpEvent =
10270 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10271 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010272 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10273 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010274 .build();
10275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010276 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010277 InputEventInjectionSync::WAIT_FOR_RESULT));
10278 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010279 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010280 mWindow->assertNoEvents();
10281 mSecondWindow->consumeMotionMove();
10282}
10283
Arthur Hung3915c1f2022-05-31 07:17:17 +000010284TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010285 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010286
10287 // Update window of second display.
10288 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010289 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010290 mDispatcher->onWindowInfosChanged(
10291 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10292 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10293 {},
10294 0,
10295 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010296
10297 // Let second display has a touch state.
10298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010299 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010300 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10301 AINPUT_SOURCE_TOUCHSCREEN)
10302 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010303 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010304 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010305 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010306 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010307 mDispatcher->onWindowInfosChanged(
10308 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10309 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10310 {},
10311 0,
10312 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010313
10314 // Move on window.
10315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010316 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010317 ADISPLAY_ID_DEFAULT, {50, 50}))
10318 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10319 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10320 mWindow->consumeDragEvent(false, 50, 50);
10321 mSecondWindow->assertNoEvents();
10322
10323 // Move to another window.
10324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010325 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010326 ADISPLAY_ID_DEFAULT, {150, 50}))
10327 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10328 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10329 mWindow->consumeDragEvent(true, 150, 50);
10330 mSecondWindow->consumeDragEvent(false, 50, 50);
10331
10332 // drop to another window.
10333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010334 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010335 {150, 50}))
10336 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10337 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010338 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010339 mWindow->assertNoEvents();
10340 mSecondWindow->assertNoEvents();
10341}
10342
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010343TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10344 startDrag(true, AINPUT_SOURCE_MOUSE);
10345 // Move on window.
10346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010347 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010348 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10349 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010350 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010351 .x(50)
10352 .y(50))
10353 .build()))
10354 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10355 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10356 mWindow->consumeDragEvent(false, 50, 50);
10357 mSecondWindow->assertNoEvents();
10358
10359 // Move to another window.
10360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010361 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010362 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10363 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010364 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010365 .x(150)
10366 .y(50))
10367 .build()))
10368 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10369 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10370 mWindow->consumeDragEvent(true, 150, 50);
10371 mSecondWindow->consumeDragEvent(false, 50, 50);
10372
10373 // drop to another window.
10374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010375 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010376 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10377 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010378 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010379 .x(150)
10380 .y(50))
10381 .build()))
10382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10383 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010384 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010385 mWindow->assertNoEvents();
10386 mSecondWindow->assertNoEvents();
10387}
10388
Linnan Li5af92f92023-07-14 14:36:22 +080010389/**
10390 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10391 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10392 */
10393TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10394 // Down on second window
10395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10396 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10397 {150, 50}))
10398 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10399
10400 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10401 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10402
10403 // Down on first window
10404 const MotionEvent secondFingerDownEvent =
10405 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10406 .displayId(ADISPLAY_ID_DEFAULT)
10407 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10408 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10409 .build();
10410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10411 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10412 InputEventInjectionSync::WAIT_FOR_RESULT))
10413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10414 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10415 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10416 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10417
10418 // Start drag on first window
10419 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10420
10421 // Trigger cancel
10422 mDispatcher->cancelCurrentTouch();
10423 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10424 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10425 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10426
10427 ASSERT_TRUE(mDispatcher->waitForIdle());
10428 // The D&D finished with nullptr
10429 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10430
10431 // Remove drag window
10432 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10433
10434 // Inject a simple gesture, ensure dispatcher not crashed
10435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10436 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10437 PointF{50, 50}))
10438 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10439 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10440
10441 const MotionEvent moveEvent =
10442 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10443 .displayId(ADISPLAY_ID_DEFAULT)
10444 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10445 .build();
10446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10447 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10448 InputEventInjectionSync::WAIT_FOR_RESULT))
10449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10450 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10451
10452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10453 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10454 {50, 50}))
10455 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10456 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10457}
10458
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010459TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10460 // Start hovering over the window.
10461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10462 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10463 ADISPLAY_ID_DEFAULT, {50, 50}));
10464
10465 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10466 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10467
10468 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10469 << "Drag and drop should not work with a hovering pointer";
10470}
10471
Vishnu Nair062a8672021-09-03 16:07:44 -070010472class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10473
10474TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10475 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010476 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10477 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010478 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010479 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10480 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010481 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010482 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010483 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010484
10485 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010486 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010487 window->assertNoEvents();
10488
Prabir Pradhan678438e2023-04-13 19:32:51 +000010489 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10490 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010491 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10492 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010493 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010494 window->assertNoEvents();
10495
10496 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010497 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010498 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010499
Prabir Pradhan678438e2023-04-13 19:32:51 +000010500 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010501 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10502
Prabir Pradhan678438e2023-04-13 19:32:51 +000010503 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10504 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010505 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10506 window->assertNoEvents();
10507}
10508
10509TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10510 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10511 std::make_shared<FakeApplicationHandle>();
10512 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010513 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10514 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010515 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010516 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010517 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010519 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10520 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010521 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010522 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010523 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10524 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010525 mDispatcher->onWindowInfosChanged(
10526 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010527 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010528 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010529
10530 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010531 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010532 window->assertNoEvents();
10533
Prabir Pradhan678438e2023-04-13 19:32:51 +000010534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10537 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010538 window->assertNoEvents();
10539
10540 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010541 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010542 mDispatcher->onWindowInfosChanged(
10543 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010544
Prabir Pradhan678438e2023-04-13 19:32:51 +000010545 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010546 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10547
Prabir Pradhan678438e2023-04-13 19:32:51 +000010548 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10549 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010550 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10551 window->assertNoEvents();
10552}
10553
10554TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10555 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10556 std::make_shared<FakeApplicationHandle>();
10557 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010558 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10559 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010560 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010561 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010562 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010564 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10565 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010566 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010567 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010568 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10569 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010570 mDispatcher->onWindowInfosChanged(
10571 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010572 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010573 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010574
10575 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010576 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010577 window->assertNoEvents();
10578
Prabir Pradhan678438e2023-04-13 19:32:51 +000010579 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10580 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010581 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10582 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010583 window->assertNoEvents();
10584
10585 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010586 mDispatcher->onWindowInfosChanged(
10587 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010588
Prabir Pradhan678438e2023-04-13 19:32:51 +000010589 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010590 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10591
Prabir Pradhan678438e2023-04-13 19:32:51 +000010592 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10593 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010594 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10595 window->assertNoEvents();
10596}
10597
Antonio Kantekf16f2832021-09-28 04:39:20 +000010598class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10599protected:
10600 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010601 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010602 sp<FakeWindowHandle> mWindow;
10603 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010604 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010605
10606 void SetUp() override {
10607 InputDispatcherTest::SetUp();
10608
10609 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010610 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010611 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010612 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010613 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010614 mSecondWindow =
10615 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010616 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010617 mThirdWindow =
10618 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10619 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10620 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010621
10622 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010623 mDispatcher->onWindowInfosChanged(
10624 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10625 {},
10626 0,
10627 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010628 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010629 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010630
Antonio Kantek15beb512022-06-13 22:35:41 +000010631 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010632 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010633 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010634 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10635 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010636 mThirdWindow->assertNoEvents();
10637 }
10638
10639 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10640 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010641 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010642 SECOND_DISPLAY_ID)) {
10643 mWindow->assertNoEvents();
10644 mSecondWindow->assertNoEvents();
10645 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010646 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010647 }
10648
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010649 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010650 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010651 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10652 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010653 mWindow->consumeTouchModeEvent(inTouchMode);
10654 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010655 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010656 }
10657};
10658
Antonio Kantek26defcf2022-02-08 01:12:27 +000010659TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010660 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010661 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10662 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010663 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010664}
10665
Antonio Kantek26defcf2022-02-08 01:12:27 +000010666TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10667 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010668 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010669 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010670 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010671 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010672 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010673 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010674 mWindow->assertNoEvents();
10675 mSecondWindow->assertNoEvents();
10676}
10677
10678TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10679 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010680 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010681 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010682 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010683 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010684 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010685}
10686
Antonio Kantekf16f2832021-09-28 04:39:20 +000010687TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010688 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010689 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10690 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010691 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010692 mWindow->assertNoEvents();
10693 mSecondWindow->assertNoEvents();
10694}
10695
Antonio Kantek15beb512022-06-13 22:35:41 +000010696TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10697 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10698 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10699 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010700 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010701 mWindow->assertNoEvents();
10702 mSecondWindow->assertNoEvents();
10703 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10704}
10705
Antonio Kantek48710e42022-03-24 14:19:30 -070010706TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10707 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10709 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010710 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10711 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10712
10713 // Then remove focus.
10714 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010715 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010716
10717 // Assert that caller can switch touch mode by owning one of the last interacted window.
10718 const WindowInfo& windowInfo = *mWindow->getInfo();
10719 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10720 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010721 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010722}
10723
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010724class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10725public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010726 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010727 std::shared_ptr<FakeApplicationHandle> application =
10728 std::make_shared<FakeApplicationHandle>();
10729 std::string name = "Fake Spy ";
10730 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010731 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10732 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010733 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010734 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010735 return spy;
10736 }
10737
10738 sp<FakeWindowHandle> createForeground() {
10739 std::shared_ptr<FakeApplicationHandle> application =
10740 std::make_shared<FakeApplicationHandle>();
10741 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010742 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10743 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010744 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010745 return window;
10746 }
10747
10748private:
10749 int mSpyCount{0};
10750};
10751
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010752using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010753/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010754 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10755 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010756TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010757 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010758 ScopedSilentDeath _silentDeath;
10759
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010760 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010761 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010762 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010763 ".* not a trusted overlay");
10764}
10765
10766/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010767 * Input injection into a display with a spy window but no foreground windows should succeed.
10768 */
10769TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010770 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010771 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010772
10773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010774 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10776 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10777}
10778
10779/**
10780 * Verify the order in which different input windows receive events. The touched foreground window
10781 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10782 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10783 * receive events before ones belows it.
10784 *
10785 * Here, we set up a scenario with four windows in the following Z order from the top:
10786 * spy1, spy2, window, spy3.
10787 * We then inject an event and verify that the foreground "window" receives it first, followed by
10788 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10789 * window.
10790 */
10791TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10792 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010793 auto spy1 = createSpy();
10794 auto spy2 = createSpy();
10795 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010796 mDispatcher->onWindowInfosChanged(
10797 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010798 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10799 const size_t numChannels = channels.size();
10800
Michael Wright8e9a8562022-02-09 13:44:29 +000010801 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010802 if (!epollFd.ok()) {
10803 FAIL() << "Failed to create epoll fd";
10804 }
10805
10806 for (size_t i = 0; i < numChannels; i++) {
10807 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10808 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10809 FAIL() << "Failed to add fd to epoll";
10810 }
10811 }
10812
10813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010814 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10816
10817 std::vector<size_t> eventOrder;
10818 std::vector<struct epoll_event> events(numChannels);
10819 for (;;) {
10820 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10821 (100ms).count());
10822 if (nFds < 0) {
10823 FAIL() << "Failed to call epoll_wait";
10824 }
10825 if (nFds == 0) {
10826 break; // epoll_wait timed out
10827 }
10828 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010829 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010830 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010831 channels[i]->consumeMotionDown();
10832 }
10833 }
10834
10835 // Verify the order in which the events were received.
10836 EXPECT_EQ(3u, eventOrder.size());
10837 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10838 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10839 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10840}
10841
10842/**
10843 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10844 */
10845TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10846 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010847 auto spy = createSpy();
10848 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010849 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010850
10851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010852 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10854 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10855 spy->assertNoEvents();
10856}
10857
10858/**
10859 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10860 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10861 * to the window.
10862 */
10863TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10864 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010865 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010866 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010867 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010868
10869 // Inject an event outside the spy window's touchable region.
10870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010871 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10873 window->consumeMotionDown();
10874 spy->assertNoEvents();
10875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010876 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10878 window->consumeMotionUp();
10879 spy->assertNoEvents();
10880
10881 // Inject an event inside the spy window's touchable region.
10882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010883 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010884 {5, 10}))
10885 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10886 window->consumeMotionDown();
10887 spy->consumeMotionDown();
10888}
10889
10890/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010891 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010892 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010893 */
10894TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10895 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010896 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010897 auto spy = createSpy();
10898 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010899 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010900 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010901 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010902
10903 // Inject an event outside the spy window's frame and touchable region.
10904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010905 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010906 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10908 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010909 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010910}
10911
10912/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010913 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10914 * pointers that are down within its bounds.
10915 */
10916TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10917 auto windowLeft = createForeground();
10918 windowLeft->setFrame({0, 0, 100, 200});
10919 auto windowRight = createForeground();
10920 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010921 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010922 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010923 mDispatcher->onWindowInfosChanged(
10924 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010925
10926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010927 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010928 {50, 50}))
10929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10930 windowLeft->consumeMotionDown();
10931 spy->consumeMotionDown();
10932
10933 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010934 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010935 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010936 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10937 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010938 .build();
10939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010940 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010941 InputEventInjectionSync::WAIT_FOR_RESULT))
10942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10943 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010944 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010945}
10946
10947/**
10948 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10949 * the spy should receive the second pointer with ACTION_DOWN.
10950 */
10951TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10952 auto window = createForeground();
10953 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010954 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010955 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010956 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010957
10958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010959 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010960 {50, 50}))
10961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10962 window->consumeMotionDown();
10963 spyRight->assertNoEvents();
10964
10965 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010966 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010967 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010968 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10969 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010970 .build();
10971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010972 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010973 InputEventInjectionSync::WAIT_FOR_RESULT))
10974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010975 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010976 spyRight->consumeMotionDown();
10977}
10978
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010979/**
10980 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10981 * windows should be allowed to control split touch.
10982 */
10983TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010984 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010985 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010986 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010987 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010988
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010989 auto window = createForeground();
10990 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010991
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010992 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010993
10994 // First finger down, no window touched.
10995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010996 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010997 {100, 200}))
10998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10999 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11000 window->assertNoEvents();
11001
11002 // Second finger down on window, the window should receive touch down.
11003 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011004 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011005 .displayId(ADISPLAY_ID_DEFAULT)
11006 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011007 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11008 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011009 .build();
11010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011011 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011012 InputEventInjectionSync::WAIT_FOR_RESULT))
11013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11014
11015 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011016 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011017}
11018
11019/**
11020 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11021 * do not receive key events.
11022 */
11023TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011024 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011025 spy->setFocusable(false);
11026
11027 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011028 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011029 setFocusedWindow(window);
11030 window->consumeFocusEvent(true);
11031
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011033 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11034 window->consumeKeyDown(ADISPLAY_ID_NONE);
11035
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011037 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11038 window->consumeKeyUp(ADISPLAY_ID_NONE);
11039
11040 spy->assertNoEvents();
11041}
11042
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011043using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11044
11045/**
11046 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11047 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11048 */
11049TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11050 auto window = createForeground();
11051 auto spy1 = createSpy();
11052 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011053 mDispatcher->onWindowInfosChanged(
11054 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011055
11056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011057 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11059 window->consumeMotionDown();
11060 spy1->consumeMotionDown();
11061 spy2->consumeMotionDown();
11062
11063 // Pilfer pointers from the second spy window.
11064 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11065 spy2->assertNoEvents();
11066 spy1->consumeMotionCancel();
11067 window->consumeMotionCancel();
11068
11069 // The rest of the gesture should only be sent to the second spy window.
11070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011071 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011072 ADISPLAY_ID_DEFAULT))
11073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11074 spy2->consumeMotionMove();
11075 spy1->assertNoEvents();
11076 window->assertNoEvents();
11077}
11078
11079/**
11080 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11081 * in the middle of the gesture.
11082 */
11083TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11084 auto window = createForeground();
11085 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011086 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011087
11088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011089 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11091 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11092 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11093
11094 window->releaseChannel();
11095
11096 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11097
11098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011099 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11101 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11102}
11103
11104/**
11105 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11106 * the spy, but not to any other windows.
11107 */
11108TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11109 auto spy = createSpy();
11110 auto window = createForeground();
11111
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011112 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011113
11114 // First finger down on the window and the spy.
11115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011116 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011117 {100, 200}))
11118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11119 spy->consumeMotionDown();
11120 window->consumeMotionDown();
11121
11122 // Spy window pilfers the pointers.
11123 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11124 window->consumeMotionCancel();
11125
11126 // Second finger down on the window and spy, but the window should not receive the pointer down.
11127 const MotionEvent secondFingerDownEvent =
11128 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11129 .displayId(ADISPLAY_ID_DEFAULT)
11130 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011131 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11132 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011133 .build();
11134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011135 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011136 InputEventInjectionSync::WAIT_FOR_RESULT))
11137 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11138
Harry Cutts33476232023-01-30 19:57:29 +000011139 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011140
11141 // Third finger goes down outside all windows, so injection should fail.
11142 const MotionEvent thirdFingerDownEvent =
11143 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11144 .displayId(ADISPLAY_ID_DEFAULT)
11145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011146 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11147 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11148 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011149 .build();
11150 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011151 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011152 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011153 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011154
11155 spy->assertNoEvents();
11156 window->assertNoEvents();
11157}
11158
11159/**
11160 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11161 */
11162TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11163 auto spy = createSpy();
11164 spy->setFrame(Rect(0, 0, 100, 100));
11165 auto window = createForeground();
11166 window->setFrame(Rect(0, 0, 200, 200));
11167
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011168 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011169
11170 // First finger down on the window only
11171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011172 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011173 {150, 150}))
11174 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11175 window->consumeMotionDown();
11176
11177 // Second finger down on the spy and window
11178 const MotionEvent secondFingerDownEvent =
11179 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11180 .displayId(ADISPLAY_ID_DEFAULT)
11181 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011182 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11183 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011184 .build();
11185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011186 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011187 InputEventInjectionSync::WAIT_FOR_RESULT))
11188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11189 spy->consumeMotionDown();
11190 window->consumeMotionPointerDown(1);
11191
11192 // Third finger down on the spy and window
11193 const MotionEvent thirdFingerDownEvent =
11194 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11195 .displayId(ADISPLAY_ID_DEFAULT)
11196 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011197 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11198 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11199 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011200 .build();
11201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011202 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011203 InputEventInjectionSync::WAIT_FOR_RESULT))
11204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11205 spy->consumeMotionPointerDown(1);
11206 window->consumeMotionPointerDown(2);
11207
11208 // Spy window pilfers the pointers.
11209 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011210 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11211 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011212
11213 spy->assertNoEvents();
11214 window->assertNoEvents();
11215}
11216
11217/**
11218 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11219 * other windows should be canceled. If this results in the cancellation of all pointers for some
11220 * window, then that window should receive ACTION_CANCEL.
11221 */
11222TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11223 auto spy = createSpy();
11224 spy->setFrame(Rect(0, 0, 100, 100));
11225 auto window = createForeground();
11226 window->setFrame(Rect(0, 0, 200, 200));
11227
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011228 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011229
11230 // First finger down on both spy and window
11231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011232 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011233 {10, 10}))
11234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11235 window->consumeMotionDown();
11236 spy->consumeMotionDown();
11237
11238 // Second finger down on the spy and window
11239 const MotionEvent secondFingerDownEvent =
11240 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11241 .displayId(ADISPLAY_ID_DEFAULT)
11242 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011243 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11244 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011245 .build();
11246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011247 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011248 InputEventInjectionSync::WAIT_FOR_RESULT))
11249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11250 spy->consumeMotionPointerDown(1);
11251 window->consumeMotionPointerDown(1);
11252
11253 // Spy window pilfers the pointers.
11254 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11255 window->consumeMotionCancel();
11256
11257 spy->assertNoEvents();
11258 window->assertNoEvents();
11259}
11260
11261/**
11262 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11263 * be sent to other windows
11264 */
11265TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11266 auto spy = createSpy();
11267 spy->setFrame(Rect(0, 0, 100, 100));
11268 auto window = createForeground();
11269 window->setFrame(Rect(0, 0, 200, 200));
11270
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011271 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011272
11273 // First finger down on both window and spy
11274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011275 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011276 {10, 10}))
11277 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11278 window->consumeMotionDown();
11279 spy->consumeMotionDown();
11280
11281 // Spy window pilfers the pointers.
11282 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11283 window->consumeMotionCancel();
11284
11285 // Second finger down on the window only
11286 const MotionEvent secondFingerDownEvent =
11287 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11288 .displayId(ADISPLAY_ID_DEFAULT)
11289 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011290 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11291 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011292 .build();
11293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011294 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011295 InputEventInjectionSync::WAIT_FOR_RESULT))
11296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11297 window->consumeMotionDown();
11298 window->assertNoEvents();
11299
11300 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11301 spy->consumeMotionMove();
11302 spy->assertNoEvents();
11303}
11304
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011305/**
11306 * A window on the left and a window on the right. Also, a spy window that's above all of the
11307 * windows, and spanning both left and right windows.
11308 * Send simultaneous motion streams from two different devices, one to the left window, and another
11309 * to the right window.
11310 * Pilfer from spy window.
11311 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11312 */
11313TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11314 sp<FakeWindowHandle> spy = createSpy();
11315 spy->setFrame(Rect(0, 0, 200, 200));
11316 sp<FakeWindowHandle> leftWindow = createForeground();
11317 leftWindow->setFrame(Rect(0, 0, 100, 100));
11318
11319 sp<FakeWindowHandle> rightWindow = createForeground();
11320 rightWindow->setFrame(Rect(100, 0, 200, 100));
11321
11322 constexpr int32_t stylusDeviceId = 1;
11323 constexpr int32_t touchDeviceId = 2;
11324
11325 mDispatcher->onWindowInfosChanged(
11326 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11327
11328 // Stylus down on left window and spy
11329 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11330 .deviceId(stylusDeviceId)
11331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11332 .build());
11333 leftWindow->consumeMotionEvent(
11334 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11335 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11336
11337 // Finger down on right window and spy - but spy already has stylus
11338 mDispatcher->notifyMotion(
11339 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11340 .deviceId(touchDeviceId)
11341 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11342 .build());
11343 rightWindow->consumeMotionEvent(
11344 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011345 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011346
11347 // Act: pilfer from spy. Spy is currently receiving touch events.
11348 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011349 leftWindow->consumeMotionEvent(
11350 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011351 rightWindow->consumeMotionEvent(
11352 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11353
11354 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11355 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11356 .deviceId(stylusDeviceId)
11357 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11358 .build());
11359 mDispatcher->notifyMotion(
11360 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11361 .deviceId(touchDeviceId)
11362 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11363 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011364 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011365
11366 spy->assertNoEvents();
11367 leftWindow->assertNoEvents();
11368 rightWindow->assertNoEvents();
11369}
11370
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011371TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11372 auto window = createForeground();
11373 auto spy = createSpy();
11374 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11375
11376 mDispatcher->notifyMotion(
11377 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11378 .deviceId(1)
11379 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11380 .build());
11381 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11382 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11383
11384 // Pilfer pointers from the spy window should fail.
11385 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11386 spy->assertNoEvents();
11387 window->assertNoEvents();
11388}
11389
Prabir Pradhand65552b2021-10-07 11:23:50 -070011390class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11391public:
11392 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11393 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11394 std::make_shared<FakeApplicationHandle>();
11395 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011396 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11397 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011398 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011399 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011400 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011401 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011402 overlay->setTrustedOverlay(true);
11403
11404 std::shared_ptr<FakeApplicationHandle> application =
11405 std::make_shared<FakeApplicationHandle>();
11406 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011407 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11408 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011409 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011410 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011411
11412 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011413 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011414 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011415 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011416 return {std::move(overlay), std::move(window)};
11417 }
11418
11419 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011420 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011421 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011422 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011423 }
11424
11425 void sendStylusEvent(int32_t action) {
11426 NotifyMotionArgs motionArgs =
11427 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11428 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011429 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011430 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011431 }
11432};
11433
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011434using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11435
11436TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011437 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011438 ScopedSilentDeath _silentDeath;
11439
Prabir Pradhand65552b2021-10-07 11:23:50 -070011440 auto [overlay, window] = setupStylusOverlayScenario();
11441 overlay->setTrustedOverlay(false);
11442 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011443 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11444 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011445 ".* not a trusted overlay");
11446}
11447
11448TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11449 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011450 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011451
11452 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11453 overlay->consumeMotionDown();
11454 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11455 overlay->consumeMotionUp();
11456
11457 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11458 window->consumeMotionDown();
11459 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11460 window->consumeMotionUp();
11461
11462 overlay->assertNoEvents();
11463 window->assertNoEvents();
11464}
11465
11466TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11467 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011468 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011469 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011470
11471 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11472 overlay->consumeMotionDown();
11473 window->consumeMotionDown();
11474 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11475 overlay->consumeMotionUp();
11476 window->consumeMotionUp();
11477
11478 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11479 window->consumeMotionDown();
11480 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11481 window->consumeMotionUp();
11482
11483 overlay->assertNoEvents();
11484 window->assertNoEvents();
11485}
11486
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011487/**
11488 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11489 * The scenario is as follows:
11490 * - The stylus interceptor overlay is configured as a spy window.
11491 * - The stylus interceptor spy receives the start of a new stylus gesture.
11492 * - It pilfers pointers and then configures itself to no longer be a spy.
11493 * - The stylus interceptor continues to receive the rest of the gesture.
11494 */
11495TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11496 auto [overlay, window] = setupStylusOverlayScenario();
11497 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011498 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011499
11500 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11501 overlay->consumeMotionDown();
11502 window->consumeMotionDown();
11503
11504 // The interceptor pilfers the pointers.
11505 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11506 window->consumeMotionCancel();
11507
11508 // The interceptor configures itself so that it is no longer a spy.
11509 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011510 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011511
11512 // It continues to receive the rest of the stylus gesture.
11513 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11514 overlay->consumeMotionMove();
11515 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11516 overlay->consumeMotionUp();
11517
11518 window->assertNoEvents();
11519}
11520
Prabir Pradhan5735a322022-04-11 17:23:34 +000011521struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011522 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011523 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011524 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11525 std::unique_ptr<InputDispatcher>& mDispatcher;
11526
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011527 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011528 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11529
11530 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011531 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011532 ADISPLAY_ID_DEFAULT, {100, 200},
11533 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11534 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11535 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11536 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11537 }
11538
11539 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011540 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011541 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011542 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011543 mPolicyFlags);
11544 }
11545
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011546 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011547 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11548 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011549 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11550 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011551 window->setOwnerInfo(mPid, mUid);
11552 return window;
11553 }
11554};
11555
11556using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11557
11558TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011559 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011560 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011561 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011562
11563 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11564 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11565 window->consumeMotionDown();
11566
11567 setFocusedWindow(window);
11568 window->consumeFocusEvent(true);
11569
11570 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11571 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11572 window->consumeKeyDown(ADISPLAY_ID_NONE);
11573}
11574
11575TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011576 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011577 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011578 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011579
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011580 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011581 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11582 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11583
11584 setFocusedWindow(window);
11585 window->consumeFocusEvent(true);
11586
11587 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11588 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11589 window->assertNoEvents();
11590}
11591
11592TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011593 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011594 auto window = owner.createWindow("Owned window");
11595 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011596 spy->setSpy(true);
11597 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011598 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011599
11600 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11601 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11602 spy->consumeMotionDown();
11603 window->consumeMotionDown();
11604}
11605
11606TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011607 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011608 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011609
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011610 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011611 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011612 randosSpy->setSpy(true);
11613 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011614 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011615
11616 // The event is targeted at owner's window, so injection should succeed, but the spy should
11617 // not receive the event.
11618 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11619 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11620 randosSpy->assertNoEvents();
11621 window->consumeMotionDown();
11622}
11623
11624TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011625 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011626 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011627
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011628 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011629 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011630 randosSpy->setSpy(true);
11631 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011632 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011633
11634 // A user that has injection permission can inject into any window.
11635 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011636 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011637 ADISPLAY_ID_DEFAULT));
11638 randosSpy->consumeMotionDown();
11639 window->consumeMotionDown();
11640
11641 setFocusedWindow(randosSpy);
11642 randosSpy->consumeFocusEvent(true);
11643
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011644 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011645 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11646 window->assertNoEvents();
11647}
11648
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011649TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011650 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011651 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011652
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011653 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011654 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011655 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11656 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011657 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011658
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011659 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011660 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11661 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11662 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011663 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011664}
11665
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011666using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11667
11668TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11670
11671 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11672 ADISPLAY_ID_DEFAULT);
11673 left->setFrame(Rect(0, 0, 100, 100));
11674 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11675 "Right Window", ADISPLAY_ID_DEFAULT);
11676 right->setFrame(Rect(100, 0, 200, 100));
11677 sp<FakeWindowHandle> spy =
11678 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11679 spy->setFrame(Rect(0, 0, 200, 100));
11680 spy->setTrustedOverlay(true);
11681 spy->setSpy(true);
11682
11683 mDispatcher->onWindowInfosChanged(
11684 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11685
11686 // Hover into the left window.
11687 mDispatcher->notifyMotion(
11688 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11689 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11690 .build());
11691
11692 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11693 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11694
11695 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11696 /*pointerId=*/0));
11697 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11698 /*pointerId=*/0));
11699 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11700 /*pointerId=*/0));
11701
11702 // Hover move to the right window.
11703 mDispatcher->notifyMotion(
11704 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11705 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11706 .build());
11707
11708 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11709 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11710 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11711
11712 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11713 /*pointerId=*/0));
11714 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11715 /*pointerId=*/0));
11716 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11717 /*pointerId=*/0));
11718
11719 // Stop hovering.
11720 mDispatcher->notifyMotion(
11721 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11722 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11723 .build());
11724
11725 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11726 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11727
11728 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11729 /*pointerId=*/0));
11730 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11731 /*pointerId=*/0));
11732 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11733 /*pointerId=*/0));
11734}
11735
11736TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11738
11739 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11740 ADISPLAY_ID_DEFAULT);
11741 left->setFrame(Rect(0, 0, 100, 100));
11742 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11743 "Right Window", ADISPLAY_ID_DEFAULT);
11744 right->setFrame(Rect(100, 0, 200, 100));
11745 sp<FakeWindowHandle> spy =
11746 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11747 spy->setFrame(Rect(0, 0, 200, 100));
11748 spy->setTrustedOverlay(true);
11749 spy->setSpy(true);
11750
11751 mDispatcher->onWindowInfosChanged(
11752 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11753
11754 // First pointer down on left window.
11755 mDispatcher->notifyMotion(
11756 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11757 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11758 .build());
11759
11760 left->consumeMotionDown();
11761 spy->consumeMotionDown();
11762
11763 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11764 /*pointerId=*/0));
11765 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11766 /*pointerId=*/0));
11767 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11768 /*pointerId=*/0));
11769
11770 // Second pointer down on right window.
11771 mDispatcher->notifyMotion(
11772 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11773 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11774 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11775 .build());
11776
11777 left->consumeMotionMove();
11778 right->consumeMotionDown();
11779 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11780
11781 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11782 /*pointerId=*/0));
11783 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11784 /*pointerId=*/0));
11785 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11786 /*pointerId=*/0));
11787 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11788 /*pointerId=*/1));
11789 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11790 /*pointerId=*/1));
11791 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11792 /*pointerId=*/1));
11793
11794 // Second pointer up.
11795 mDispatcher->notifyMotion(
11796 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11797 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11798 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11799 .build());
11800
11801 left->consumeMotionMove();
11802 right->consumeMotionUp();
11803 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11804
11805 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11806 /*pointerId=*/0));
11807 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11808 /*pointerId=*/0));
11809 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11810 /*pointerId=*/0));
11811 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11812 /*pointerId=*/1));
11813 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11814 /*pointerId=*/1));
11815 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11816 /*pointerId=*/1));
11817
11818 // First pointer up.
11819 mDispatcher->notifyMotion(
11820 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11821 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11822 .build());
11823
11824 left->consumeMotionUp();
11825 spy->consumeMotionUp();
11826
11827 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11828 /*pointerId=*/0));
11829 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11830 /*pointerId=*/0));
11831 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11832 /*pointerId=*/0));
11833}
11834
11835TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11836 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11837
11838 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11839 ADISPLAY_ID_DEFAULT);
11840 left->setFrame(Rect(0, 0, 100, 100));
11841 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11842 "Right Window", ADISPLAY_ID_DEFAULT);
11843 right->setFrame(Rect(100, 0, 200, 100));
11844
11845 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11846
11847 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11848 /*pointerId=*/0));
11849 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11850 /*pointerId=*/0));
11851
11852 // Hover move into the window.
11853 mDispatcher->notifyMotion(
11854 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11855 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11856 .rawXCursorPosition(50)
11857 .rawYCursorPosition(50)
11858 .deviceId(DEVICE_ID)
11859 .build());
11860
11861 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11862
11863 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11864 /*pointerId=*/0));
11865
11866 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11867 mDispatcher->notifyMotion(
11868 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11869 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11870 .rawXCursorPosition(51)
11871 .rawYCursorPosition(50)
11872 .deviceId(SECOND_DEVICE_ID)
11873 .build());
11874
11875 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11876 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11877
11878 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11879 // a HOVER_EXIT from the first device.
11880 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11881 /*pointerId=*/0));
11882 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11883 SECOND_DEVICE_ID,
11884 /*pointerId=*/0));
11885
11886 // Move the mouse outside the window. Document the current behavior, where the window does not
11887 // receive HOVER_EXIT even though the mouse left the window.
11888 mDispatcher->notifyMotion(
11889 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11890 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11891 .rawXCursorPosition(150)
11892 .rawYCursorPosition(50)
11893 .deviceId(SECOND_DEVICE_ID)
11894 .build());
11895
11896 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11897 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11898 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11899 /*pointerId=*/0));
11900 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11901 SECOND_DEVICE_ID,
11902 /*pointerId=*/0));
11903}
11904
Garfield Tane84e6f92019-08-29 17:28:41 -070011905} // namespace android::inputdispatcher