blob: c0465d849647f20281dd5789ff5a85f52c7df2ff [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,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001093 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001094 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001095 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001096 base::Result<std::unique_ptr<InputChannel>> channel =
1097 dispatcher->createInputChannel(name);
1098 token = (*channel)->getConnectionToken();
1099 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001100 }
1101
1102 inputApplicationHandle->updateInfo();
1103 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1104
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001105 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001106 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001107 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001108 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001109 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001110 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001111 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001112 mInfo.globalScaleFactor = 1.0;
1113 mInfo.touchableRegion.clear();
1114 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001115 mInfo.ownerPid = WINDOW_PID;
1116 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001117 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001118 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001119 }
1120
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001121 sp<FakeWindowHandle> clone(int32_t displayId) {
1122 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1123 handle->mInfo = mInfo;
1124 handle->mInfo.displayId = displayId;
1125 handle->mInfo.id = sId++;
1126 handle->mInputReceiver = mInputReceiver;
1127 return handle;
1128 }
1129
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001130 void setTouchable(bool touchable) {
1131 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1132 }
chaviwd1c23182019-12-20 18:44:56 -08001133
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001134 void setFocusable(bool focusable) {
1135 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1136 }
1137
1138 void setVisible(bool visible) {
1139 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1140 }
Vishnu Nair958da932020-08-21 17:12:37 -07001141
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001142 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001143 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001144 }
1145
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001146 void setPaused(bool paused) {
1147 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1148 }
1149
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001150 void setPreventSplitting(bool preventSplitting) {
1151 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001152 }
1153
1154 void setSlippery(bool slippery) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1156 }
1157
1158 void setWatchOutsideTouch(bool watchOutside) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1160 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001161
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001162 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1163
1164 void setInterceptsStylus(bool interceptsStylus) {
1165 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1166 }
1167
1168 void setDropInput(bool dropInput) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1170 }
1171
1172 void setDropInputIfObscured(bool dropInputIfObscured) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1174 }
1175
1176 void setNoInputChannel(bool noInputChannel) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1178 }
1179
Josep del Riob3981622023-04-18 15:49:45 +00001180 void setDisableUserActivity(bool disableUserActivity) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1182 }
1183
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001184 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1186 shouldGlobalStylusBlockTouch);
1187 }
1188
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001189 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1190
chaviw3277faf2021-05-19 16:45:23 -05001191 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001192
Bernardo Rufino7393d172021-02-26 13:56:11 +00001193 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1194
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001195 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001196 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001197 mInfo.touchableRegion.clear();
1198 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001199
1200 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1201 ui::Transform translate;
1202 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1203 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001204 }
1205
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001206 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1207
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001208 void setIsWallpaper(bool isWallpaper) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1210 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setDupTouchToWallpaper(bool hasWallpaper) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1214 }
chaviwd1c23182019-12-20 18:44:56 -08001215
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 void setTrustedOverlay(bool trustedOverlay) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1218 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001219
chaviw9eaa22c2020-07-01 16:21:27 -07001220 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1221 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1222 }
1223
1224 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001225
yunho.shinf4a80b82020-11-16 21:13:57 +09001226 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1227
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001228 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1229 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1230 if (event == nullptr) {
1231 ADD_FAILURE() << "No event";
1232 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001233 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001234 if (event->getType() != InputEventType::KEY) {
1235 ADD_FAILURE() << "Instead of key event, got " << event;
1236 return nullptr;
1237 }
1238 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001239 }
1240
1241 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001242 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1243 ASSERT_NE(nullptr, keyEvent);
1244 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001245 }
1246
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001247 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001248 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1249 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001250 }
1251
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001252 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001253 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1254 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001255 }
1256
Svet Ganov5d3bc372020-01-26 23:11:07 -08001257 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001258 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001259 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1260 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 }
1262
1263 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001265 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1266 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001267 }
1268
1269 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001270 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001271 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1272 }
1273
1274 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1275 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001276 consumeMotionEvent(
1277 AllOf(WithMotionAction(ACTION_DOWN),
1278 testing::Conditional(expectedDisplayId.has_value(),
1279 WithDisplayId(*expectedDisplayId), testing::_),
1280 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1281 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001282 }
1283
Svet Ganov5d3bc372020-01-26 23:11:07 -08001284 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1286 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001287 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001288 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001289 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1290 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001291 }
1292
1293 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001294 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001295 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001296 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001297 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1298 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001299 }
1300
1301 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001302 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001303 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1304 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001305 }
1306
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001307 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1308 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001309 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1310 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001311 }
1312
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001313 void consumeMotionOutsideWithZeroedCoords() {
1314 consumeMotionEvent(
1315 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001316 }
1317
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001318 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1319 ASSERT_NE(mInputReceiver, nullptr)
1320 << "Cannot consume events from a window with no receiver";
1321 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1322 }
1323
Prabir Pradhan99987712020-11-10 18:43:05 -08001324 void consumeCaptureEvent(bool hasCapture) {
1325 ASSERT_NE(mInputReceiver, nullptr)
1326 << "Cannot consume events from a window with no receiver";
1327 mInputReceiver->consumeCaptureEvent(hasCapture);
1328 }
1329
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001330 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001331 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001332 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1333 if (event == nullptr) {
1334 ADD_FAILURE() << "No event";
1335 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001336 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001337 if (event->getType() != InputEventType::MOTION) {
1338 ADD_FAILURE() << "Instead of motion event, got " << *event;
1339 return nullptr;
1340 }
1341 std::unique_ptr<MotionEvent> motionEvent =
1342 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1343 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001344 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001345 }
1346
arthurhungb89ccb02020-12-30 16:19:01 +08001347 void consumeDragEvent(bool isExiting, float x, float y) {
1348 mInputReceiver->consumeDragEvent(isExiting, x, y);
1349 }
1350
Antonio Kantekf16f2832021-09-28 04:39:20 +00001351 void consumeTouchModeEvent(bool inTouchMode) {
1352 ASSERT_NE(mInputReceiver, nullptr)
1353 << "Cannot consume events from a window with no receiver";
1354 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1355 }
1356
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001357 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001358 if (mInputReceiver == nullptr) {
1359 ADD_FAILURE() << "Invalid receive event on window with no receiver";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001360 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001361 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001362 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001363 }
1364
1365 void finishEvent(uint32_t sequenceNum) {
1366 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1367 mInputReceiver->finishEvent(sequenceNum);
1368 }
1369
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001370 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1371 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1372 mInputReceiver->sendTimeline(inputEventId, timeline);
1373 }
1374
Arthur Hungb92218b2018-08-14 12:00:21 +08001375 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001376 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001377 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001378 return; // Can't receive events if the window does not have input channel
1379 }
1380 ASSERT_NE(nullptr, mInputReceiver)
1381 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001382 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001383 }
1384
chaviwaf87b3e2019-10-01 16:59:28 -07001385 sp<IBinder> getToken() { return mInfo.token; }
1386
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001387 const std::string& getName() { return mName; }
1388
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001389 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001390 mInfo.ownerPid = ownerPid;
1391 mInfo.ownerUid = ownerUid;
1392 }
1393
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001394 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001395
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001396 void destroyReceiver() { mInputReceiver = nullptr; }
1397
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001398 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1399
chaviwd1c23182019-12-20 18:44:56 -08001400private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001401 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001402 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001403 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001404 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001405 friend class sp<FakeWindowHandle>;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001406
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001407 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001408 if (mInputReceiver == nullptr) {
1409 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1410 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001411 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001412 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001413 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001414 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001415 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001416 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001417};
1418
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001419std::atomic<int32_t> FakeWindowHandle::sId{1};
1420
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001421class FakeMonitorReceiver {
1422public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001423 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1424 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001425
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001426 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001427
1428 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001429 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1430 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001431 }
1432
1433 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001434 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1435 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001436 }
1437
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001438 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001439
1440 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001441 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1442 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001443 }
1444
1445 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001446 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1447 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001448 }
1449
1450 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001451 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1452 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001453 }
1454
1455 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001456 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001457 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1458 WithDisplayId(expectedDisplayId),
1459 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1460 }
1461
1462 void consumeMotionPointerDown(int32_t pointerIdx) {
1463 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1464 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001465 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1466 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467 }
1468
1469 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001470 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001471 }
1472
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001473 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001474
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001475 void assertNoEvents() { mInputReceiver.assertNoEvents(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001476
1477private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001478 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001479};
1480
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001481static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001482 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001483 int32_t displayId = ADISPLAY_ID_NONE,
1484 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001485 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001486 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001487 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001488 KeyEvent event;
1489 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1490
1491 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001492 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001493 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1494 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001495
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496 if (!allowKeyRepeat) {
1497 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1498 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001499 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001500 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001501}
1502
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001503static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1504 InputEventInjectionResult result =
1505 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1506 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1507 if (result != InputEventInjectionResult::TIMED_OUT) {
1508 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1509 }
1510}
1511
1512static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001513 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001514 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001515}
1516
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001517// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1518// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1519// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001520static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1521 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001522 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001523 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001524 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001525}
1526
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001527static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001528 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001529 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001530}
1531
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001533 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001534 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001535 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001536 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001537 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1538 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001539}
1540
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001541static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001542 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1543 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001544 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001545 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1546 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001547 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001548 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001549 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001550 MotionEventBuilder motionBuilder =
1551 MotionEventBuilder(action, source)
1552 .displayId(displayId)
1553 .eventTime(eventTime)
1554 .rawXCursorPosition(cursorPosition.x)
1555 .rawYCursorPosition(cursorPosition.y)
1556 .pointer(
1557 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1558 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1559 motionBuilder.downTime(eventTime);
1560 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001561
1562 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001563 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1564 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001565}
1566
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001567static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1568 int32_t displayId,
1569 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001570 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001571}
1572
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001573static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1574 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001575 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001576 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001577}
1578
Jackal Guof9696682018-10-05 12:23:23 +08001579static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1580 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1581 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001582 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1583 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1584 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001585
1586 return args;
1587}
1588
Josep del Riob3981622023-04-18 15:49:45 +00001589static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1590 int32_t displayId = ADISPLAY_ID_NONE) {
1591 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1592 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001593 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1594 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1595 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001596
1597 return args;
1598}
1599
1600static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1601 int32_t displayId = ADISPLAY_ID_NONE) {
1602 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1603 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001604 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1605 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1606 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001607
1608 return args;
1609}
1610
Prabir Pradhan678438e2023-04-13 19:32:51 +00001611[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1612 int32_t displayId,
1613 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001614 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001615 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1616 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1617 }
1618
chaviwd1c23182019-12-20 18:44:56 -08001619 PointerProperties pointerProperties[pointerCount];
1620 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001621
chaviwd1c23182019-12-20 18:44:56 -08001622 for (size_t i = 0; i < pointerCount; i++) {
1623 pointerProperties[i].clear();
1624 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001625 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001626
chaviwd1c23182019-12-20 18:44:56 -08001627 pointerCoords[i].clear();
1628 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1629 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1630 }
Jackal Guof9696682018-10-05 12:23:23 +08001631
1632 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1633 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001634 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1635 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1636 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001637 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001638 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001639 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001640 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001641
1642 return args;
1643}
1644
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001645static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1646 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1647}
1648
chaviwd1c23182019-12-20 18:44:56 -08001649static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1650 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1651}
1652
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001653static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1654 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001655 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1656 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001657}
1658
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001659} // namespace
1660
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001661/**
1662 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1663 * broken channel.
1664 */
1665TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1667 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001668 sp<FakeWindowHandle>::make(application, mDispatcher,
1669 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001670
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001672
1673 // Window closes its channel, but the window remains.
1674 window->destroyReceiver();
1675 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1676}
1677
Arthur Hungb92218b2018-08-14 12:00:21 +08001678TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001680 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1681 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001682
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001683 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001685 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001687
1688 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001689 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001690}
1691
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001692TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001694 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1695 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001696
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001697 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001698 // Inject a MotionEvent to an unknown display.
1699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001700 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1702
1703 // Window should receive motion event.
1704 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1705}
1706
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001708 * Calling onWindowInfosChanged once should not cause any issues.
1709 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710 * called twice.
1711 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001712TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1715 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001716 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001721 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001723
1724 // Window should receive motion event.
1725 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1726}
1727
1728/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001729 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001730 */
1731TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
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});
1738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001740 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001741 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001743
1744 // Window should receive motion event.
1745 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1746}
1747
Arthur Hungb92218b2018-08-14 12:00:21 +08001748// The foreground window should receive the first touch down event.
1749TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001751 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001752 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001753 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001754 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001755
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001756 mDispatcher->onWindowInfosChanged(
1757 {{*windowTop->getInfo(), *windowSecond->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 Vishniakouae6229e2019-12-30 16:23:19 -08001760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001761
1762 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001763 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001764 windowSecond->assertNoEvents();
1765}
1766
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001767/**
1768 * Two windows: A top window, and a wallpaper behind the window.
1769 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1770 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001771 * 1. foregroundWindow <-- dup touch to wallpaper
1772 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001773 */
1774TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1776 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001777 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001778 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001779 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001780 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001781 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001782
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001783 mDispatcher->onWindowInfosChanged(
1784 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001786 injectMotionEvent(*mDispatcher,
1787 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1788 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1789 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1791
1792 // Both foreground window and its wallpaper should receive the touch down
1793 foregroundWindow->consumeMotionDown();
1794 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1795
1796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001797 injectMotionEvent(*mDispatcher,
1798 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1799 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1800 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1802
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001803 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001804 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1805
1806 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001807 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001808 foregroundWindow->consumeMotionCancel();
1809 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1810 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1811}
1812
1813/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001814 * Two fingers down on the window, and lift off the first finger.
1815 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1816 * contains a single pointer.
1817 */
1818TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1820 sp<FakeWindowHandle> window =
1821 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1822
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001824 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1826 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1827 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001828 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001829 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1830 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1831 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1832 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001833 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001834 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1835 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1836 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1837 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001838 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1839 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1840 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1841
1842 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001843 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001844 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1845 window->consumeMotionEvent(
1846 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1847}
1848
1849/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001850 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1851 * with the following differences:
1852 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1853 * clean up the connection.
1854 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1855 * Ensure that there's no crash in the dispatcher.
1856 */
1857TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1859 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001860 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001861 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001863 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001864 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001865
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001866 mDispatcher->onWindowInfosChanged(
1867 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001870 {100, 200}))
1871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1872
1873 // Both foreground window and its wallpaper should receive the touch down
1874 foregroundWindow->consumeMotionDown();
1875 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1876
1877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001878 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001879 ADISPLAY_ID_DEFAULT, {110, 200}))
1880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1881
1882 foregroundWindow->consumeMotionMove();
1883 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1884
1885 // Wallpaper closes its channel, but the window remains.
1886 wallpaperWindow->destroyReceiver();
1887 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1888
1889 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1890 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001891 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001892 foregroundWindow->consumeMotionCancel();
1893}
1894
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895class ShouldSplitTouchFixture : public InputDispatcherTest,
1896 public ::testing::WithParamInterface<bool> {};
1897INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1898 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001899/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900 * A single window that receives touch (on top), and a wallpaper window underneath it.
1901 * The top window gets a multitouch gesture.
1902 * Ensure that wallpaper gets the same gesture.
1903 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001904TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001906 sp<FakeWindowHandle> foregroundWindow =
1907 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1908 foregroundWindow->setDupTouchToWallpaper(true);
1909 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001910
1911 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001912 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001913 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001914
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001915 mDispatcher->onWindowInfosChanged(
1916 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917
1918 // Touch down on top window
1919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001920 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001921 {100, 100}))
1922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1923
1924 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001925 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001926 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1927
1928 // Second finger down on the top window
1929 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001930 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001931 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001932 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1933 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934 .build();
1935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001936 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001937 InputEventInjectionSync::WAIT_FOR_RESULT))
1938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1939
Harry Cutts33476232023-01-30 19:57:29 +00001940 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1941 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001942 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001943
1944 const MotionEvent secondFingerUpEvent =
1945 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1946 .displayId(ADISPLAY_ID_DEFAULT)
1947 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001948 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1949 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001950 .build();
1951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001952 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001953 InputEventInjectionSync::WAIT_FOR_RESULT))
1954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1955 foregroundWindow->consumeMotionPointerUp(0);
1956 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1957
1958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001959 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001960 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1961 AINPUT_SOURCE_TOUCHSCREEN)
1962 .displayId(ADISPLAY_ID_DEFAULT)
1963 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001964 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001965 .x(100)
1966 .y(100))
1967 .build(),
1968 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1970 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1971 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001972}
1973
1974/**
1975 * Two windows: a window on the left and window on the right.
1976 * A third window, wallpaper, is behind both windows, and spans both top windows.
1977 * The first touch down goes to the left window. A second pointer touches down on the right window.
1978 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1979 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1980 * ACTION_POINTER_DOWN(1).
1981 */
1982TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1984 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001985 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001986 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001987 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988
1989 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001990 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001992 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993
1994 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001995 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001996 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001997 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001999 mDispatcher->onWindowInfosChanged(
2000 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2001 {},
2002 0,
2003 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004
2005 // Touch down on left window
2006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002007 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002008 {100, 100}))
2009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2010
2011 // Both foreground window and its wallpaper should receive the touch down
2012 leftWindow->consumeMotionDown();
2013 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2014
2015 // Second finger down on the right window
2016 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002017 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002018 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002019 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2020 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 .build();
2022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002023 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002024 InputEventInjectionSync::WAIT_FOR_RESULT))
2025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2026
2027 leftWindow->consumeMotionMove();
2028 // Since the touch is split, right window gets ACTION_DOWN
2029 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002030 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002031 expectedWallpaperFlags);
2032
2033 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002034 mDispatcher->onWindowInfosChanged(
2035 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002036 leftWindow->consumeMotionCancel();
2037 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2038 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2039
2040 // The pointer that's still down on the right window moves, and goes to the right window only.
2041 // As far as the dispatcher's concerned though, both pointers are still present.
2042 const MotionEvent secondFingerMoveEvent =
2043 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2044 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002045 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2046 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002047 .build();
2048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002049 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002050 InputEventInjectionSync::WAIT_FOR_RESULT));
2051 rightWindow->consumeMotionMove();
2052
2053 leftWindow->assertNoEvents();
2054 rightWindow->assertNoEvents();
2055 wallpaperWindow->assertNoEvents();
2056}
2057
Arthur Hungc539dbb2022-12-08 07:45:36 +00002058/**
2059 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2060 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2061 * The right window should receive ACTION_DOWN.
2062 */
2063TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065 sp<FakeWindowHandle> leftWindow =
2066 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2067 leftWindow->setFrame(Rect(0, 0, 200, 200));
2068 leftWindow->setDupTouchToWallpaper(true);
2069 leftWindow->setSlippery(true);
2070
2071 sp<FakeWindowHandle> rightWindow =
2072 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2073 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002074
2075 sp<FakeWindowHandle> wallpaperWindow =
2076 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2077 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002078
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002079 mDispatcher->onWindowInfosChanged(
2080 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2081 {},
2082 0,
2083 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002084
Arthur Hungc539dbb2022-12-08 07:45:36 +00002085 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002087 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002088 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002090
2091 // Both foreground window and its wallpaper should receive the touch down
2092 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002093 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2094
Arthur Hungc539dbb2022-12-08 07:45:36 +00002095 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002097 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002098 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2100
Arthur Hungc539dbb2022-12-08 07:45:36 +00002101 leftWindow->consumeMotionCancel();
2102 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2103 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002104}
2105
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002106/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002107 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2108 * interactive, it might stop sending this flag.
2109 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2110 * to have a consistent input stream.
2111 *
2112 * Test procedure:
2113 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2114 * DOWN (new gesture).
2115 *
2116 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2117 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2118 *
2119 * We technically just need a single window here, but we are using two windows (spy on top and a
2120 * regular window below) to emulate the actual situation where it happens on the device.
2121 */
2122TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2123 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2124 sp<FakeWindowHandle> spyWindow =
2125 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2126 spyWindow->setFrame(Rect(0, 0, 200, 200));
2127 spyWindow->setTrustedOverlay(true);
2128 spyWindow->setSpy(true);
2129
2130 sp<FakeWindowHandle> window =
2131 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2132 window->setFrame(Rect(0, 0, 200, 200));
2133
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002134 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002136
2137 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002138 mDispatcher->notifyMotion(
2139 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2140 .deviceId(touchDeviceId)
2141 .policyFlags(DEFAULT_POLICY_FLAGS)
2142 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2143 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002144
Prabir Pradhan678438e2023-04-13 19:32:51 +00002145 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2146 .deviceId(touchDeviceId)
2147 .policyFlags(DEFAULT_POLICY_FLAGS)
2148 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2149 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2150 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002151 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2152 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2153 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2154 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2155
2156 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002157 mDispatcher->notifyMotion(
2158 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2159 .deviceId(touchDeviceId)
2160 .policyFlags(0)
2161 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2162 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2163 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002164 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2165 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2166
2167 // We don't need to reset the device to reproduce the issue, but the reset event typically
2168 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002169 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002170
2171 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002172 mDispatcher->notifyMotion(
2173 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2174 .deviceId(touchDeviceId)
2175 .policyFlags(DEFAULT_POLICY_FLAGS)
2176 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2177 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002178 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2179 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2180
2181 // No more events
2182 spyWindow->assertNoEvents();
2183 window->assertNoEvents();
2184}
2185
2186/**
Linnan Li907ae732023-09-05 17:14:21 +08002187 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2188 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2189 * interactive, it might stop sending this flag.
2190 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2191 * the consistency of the hover event in this case.
2192 *
2193 * Test procedure:
2194 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2195 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2196 *
2197 * We expect to receive two full streams of hover events.
2198 */
2199TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2200 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2201
2202 sp<FakeWindowHandle> window =
2203 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2204 window->setFrame(Rect(0, 0, 300, 300));
2205
2206 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2207
2208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2209 .policyFlags(DEFAULT_POLICY_FLAGS)
2210 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2211 .build());
2212 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2213
2214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2215 .policyFlags(DEFAULT_POLICY_FLAGS)
2216 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2217 .build());
2218 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2219
2220 // Send hover exit without the default policy flags.
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2222 .policyFlags(0)
2223 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2224 .build());
2225
2226 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2227
2228 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2229 // right event.
2230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2231 .policyFlags(DEFAULT_POLICY_FLAGS)
2232 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2233 .build());
2234 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2235
2236 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2237 .policyFlags(DEFAULT_POLICY_FLAGS)
2238 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2239 .build());
2240 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2241
2242 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2243 .policyFlags(DEFAULT_POLICY_FLAGS)
2244 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2245 .build());
2246 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2247}
2248
2249/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002250 * Two windows: a window on the left and a window on the right.
2251 * Mouse is hovered from the right window into the left window.
2252 * Next, we tap on the left window, where the cursor was last seen.
2253 * The second tap is done onto the right window.
2254 * The mouse and tap are from two different devices.
2255 * We technically don't need to set the downtime / eventtime for these events, but setting these
2256 * explicitly helps during debugging.
2257 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2258 * In the buggy implementation, a tap on the right window would cause a crash.
2259 */
2260TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2262 sp<FakeWindowHandle> leftWindow =
2263 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2264 leftWindow->setFrame(Rect(0, 0, 200, 200));
2265
2266 sp<FakeWindowHandle> rightWindow =
2267 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2268 rightWindow->setFrame(Rect(200, 0, 400, 200));
2269
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002270 mDispatcher->onWindowInfosChanged(
2271 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002272 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2273 // stale.
2274 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2275 const int32_t mouseDeviceId = 6;
2276 const int32_t touchDeviceId = 4;
2277 // Move the cursor from right
2278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002279 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002280 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2281 AINPUT_SOURCE_MOUSE)
2282 .deviceId(mouseDeviceId)
2283 .downTime(baseTime + 10)
2284 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002285 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002286 .build()));
2287 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2288
2289 // .. to the left window
2290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002291 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002292 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2293 AINPUT_SOURCE_MOUSE)
2294 .deviceId(mouseDeviceId)
2295 .downTime(baseTime + 10)
2296 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002297 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002298 .build()));
2299 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2300 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2301 // Now tap the left window
2302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002303 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002304 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2305 AINPUT_SOURCE_TOUCHSCREEN)
2306 .deviceId(touchDeviceId)
2307 .downTime(baseTime + 40)
2308 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002309 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002310 .build()));
2311 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2312 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2313
2314 // release tap
2315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002316 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002317 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2318 AINPUT_SOURCE_TOUCHSCREEN)
2319 .deviceId(touchDeviceId)
2320 .downTime(baseTime + 40)
2321 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002322 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002323 .build()));
2324 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2325
2326 // Tap the window on the right
2327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002328 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002329 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2330 AINPUT_SOURCE_TOUCHSCREEN)
2331 .deviceId(touchDeviceId)
2332 .downTime(baseTime + 60)
2333 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002334 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002335 .build()));
2336 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2337
2338 // release tap
2339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002340 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002341 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2342 AINPUT_SOURCE_TOUCHSCREEN)
2343 .deviceId(touchDeviceId)
2344 .downTime(baseTime + 60)
2345 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002346 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002347 .build()));
2348 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2349
2350 // No more events
2351 leftWindow->assertNoEvents();
2352 rightWindow->assertNoEvents();
2353}
2354
2355/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002356 * Start hovering in a window. While this hover is still active, make another window appear on top.
2357 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2358 * While the top window is present, the hovering is stopped.
2359 * Later, hovering gets resumed again.
2360 * Ensure that new hover gesture is handled correctly.
2361 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2362 * to the window that's currently being hovered over.
2363 */
2364TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2366 sp<FakeWindowHandle> window =
2367 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2368 window->setFrame(Rect(0, 0, 200, 200));
2369
2370 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002371 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002372
2373 // Start hovering in the window
2374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2376 .build());
2377 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2378
2379 // Now, an obscuring window appears!
2380 sp<FakeWindowHandle> obscuringWindow =
2381 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2382 ADISPLAY_ID_DEFAULT,
2383 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2384 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2385 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2386 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2387 obscuringWindow->setNoInputChannel(true);
2388 obscuringWindow->setFocusable(false);
2389 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002390 mDispatcher->onWindowInfosChanged(
2391 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002392
2393 // While this new obscuring window is present, the hovering is stopped
2394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2395 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2396 .build());
2397 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2398
2399 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002400 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002401
2402 // And a new hover gesture starts.
2403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2405 .build());
2406 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2407}
2408
2409/**
2410 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2411 * the obscuring window.
2412 */
2413TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2415 sp<FakeWindowHandle> window =
2416 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2417 window->setFrame(Rect(0, 0, 200, 200));
2418
2419 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002420 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002421
2422 // Start hovering in the window
2423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2424 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2425 .build());
2426 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2427
2428 // Now, an obscuring window appears!
2429 sp<FakeWindowHandle> obscuringWindow =
2430 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2431 ADISPLAY_ID_DEFAULT,
2432 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2433 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2434 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2435 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2436 obscuringWindow->setNoInputChannel(true);
2437 obscuringWindow->setFocusable(false);
2438 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002439 mDispatcher->onWindowInfosChanged(
2440 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002441
2442 // While this new obscuring window is present, the hovering continues. The event can't go to the
2443 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2445 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2446 .build());
2447 obscuringWindow->assertNoEvents();
2448 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2449
2450 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002451 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002452
2453 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2454 // so it should generate a HOVER_ENTER
2455 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2456 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2457 .build());
2458 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2459
2460 // Now the MOVE should be getting dispatched normally
2461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2462 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2463 .build());
2464 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2465}
2466
2467/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002468 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2469 * events are delivered to the window.
2470 */
2471TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2473 sp<FakeWindowHandle> window =
2474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2475 window->setFrame(Rect(0, 0, 200, 200));
2476 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2477
2478 // Start hovering in the window
2479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2480 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2481 .build());
2482 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2483
2484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2485 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2486 .build());
2487 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2488
2489 // Scroll with the mouse
2490 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2491 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2492 .build());
2493 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2494}
2495
2496using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2497
2498/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002499 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2500 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002501 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002502TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2504 sp<FakeWindowHandle> window =
2505 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2506 window->setFrame(Rect(0, 0, 200, 200));
2507
2508 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2509
2510 constexpr int32_t touchDeviceId = 4;
2511 constexpr int32_t stylusDeviceId = 2;
2512
2513 // Stylus down
2514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2515 .deviceId(stylusDeviceId)
2516 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2517 .build());
2518 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2519
2520 // Touch down
2521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2522 .deviceId(touchDeviceId)
2523 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2524 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002525
2526 // Touch move
2527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2528 .deviceId(touchDeviceId)
2529 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2530 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002531 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002532
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002533 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2535 .deviceId(stylusDeviceId)
2536 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2537 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002538 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2539 WithCoords(101, 111)));
2540
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002541 window->assertNoEvents();
2542}
2543
2544/**
2545 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002546 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002547 * Similar test as above, but with added SPY window.
2548 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002549TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2551 sp<FakeWindowHandle> window =
2552 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2553 sp<FakeWindowHandle> spyWindow =
2554 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2555 spyWindow->setFrame(Rect(0, 0, 200, 200));
2556 spyWindow->setTrustedOverlay(true);
2557 spyWindow->setSpy(true);
2558 window->setFrame(Rect(0, 0, 200, 200));
2559
2560 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2561
2562 constexpr int32_t touchDeviceId = 4;
2563 constexpr int32_t stylusDeviceId = 2;
2564
2565 // Stylus down
2566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2567 .deviceId(stylusDeviceId)
2568 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2569 .build());
2570 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2571 spyWindow->consumeMotionEvent(
2572 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2573
2574 // Touch down
2575 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2576 .deviceId(touchDeviceId)
2577 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2578 .build());
2579
2580 // Touch move
2581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2582 .deviceId(touchDeviceId)
2583 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2584 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002585
2586 // Touch is ignored because stylus is already down
2587
2588 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2590 .deviceId(stylusDeviceId)
2591 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2592 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002593 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2594 WithCoords(101, 111)));
2595 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2596 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002597
2598 window->assertNoEvents();
2599 spyWindow->assertNoEvents();
2600}
2601
2602/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002603 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002604 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002605 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002606TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2608 sp<FakeWindowHandle> window =
2609 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2610 window->setFrame(Rect(0, 0, 200, 200));
2611
2612 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2613
2614 constexpr int32_t touchDeviceId = 4;
2615 constexpr int32_t stylusDeviceId = 2;
2616
2617 // Stylus down on the window
2618 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2619 .deviceId(stylusDeviceId)
2620 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2621 .build());
2622 window->consumeMotionEvent(
2623 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2624
2625 // Touch down on window
2626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2627 .deviceId(touchDeviceId)
2628 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2629 .build());
2630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2631 .deviceId(touchDeviceId)
2632 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2633 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002634
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002635 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002636
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002637 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002638 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2639 .deviceId(stylusDeviceId)
2640 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2641 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002642 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2643 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002644
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002645 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2647 .deviceId(touchDeviceId)
2648 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2649 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002650 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002651}
2652
2653/**
2654 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002655 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002656 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002657TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002658 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2659 sp<FakeWindowHandle> window =
2660 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2661 window->setFrame(Rect(0, 0, 200, 200));
2662
2663 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2664
2665 constexpr int32_t touchDeviceId = 4;
2666 constexpr int32_t stylusDeviceId = 2;
2667
2668 // Touch down on window
2669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2670 .deviceId(touchDeviceId)
2671 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2672 .build());
2673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2674 .deviceId(touchDeviceId)
2675 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2676 .build());
2677 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2678 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2679
2680 // Stylus hover on the window
2681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2682 .deviceId(stylusDeviceId)
2683 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2684 .build());
2685 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2686 .deviceId(stylusDeviceId)
2687 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2688 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002689 // Stylus hover movement causes touch to be canceled
2690 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2691 WithCoords(141, 146)));
2692 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2693 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2694 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2695 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002696
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002697 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2699 .deviceId(touchDeviceId)
2700 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2701 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002702
2703 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002704}
2705
2706/**
2707 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2708 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2709 * become active.
2710 */
2711TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2713 sp<FakeWindowHandle> window =
2714 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2715 window->setFrame(Rect(0, 0, 200, 200));
2716
2717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2718
2719 constexpr int32_t stylusDeviceId1 = 3;
2720 constexpr int32_t stylusDeviceId2 = 5;
2721
2722 // Touch down on window
2723 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2724 .deviceId(stylusDeviceId1)
2725 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2726 .build());
2727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2728 .deviceId(stylusDeviceId1)
2729 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2730 .build());
2731 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2732 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2733
2734 // Second stylus down
2735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2736 .deviceId(stylusDeviceId2)
2737 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2738 .build());
2739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2740 .deviceId(stylusDeviceId2)
2741 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2742 .build());
2743
2744 // First stylus is canceled, second one takes over.
2745 window->consumeMotionEvent(
2746 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2747 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2748 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2749
2750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2751 .deviceId(stylusDeviceId1)
2752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2753 .build());
2754 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002755 window->assertNoEvents();
2756}
2757
2758/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002759 * One window. Touch down on the window. Then, stylus down on the window from another device.
2760 * Ensure that is canceled, because stylus down should be preferred over touch.
2761 */
2762TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2763 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2764 sp<FakeWindowHandle> window =
2765 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2766 window->setFrame(Rect(0, 0, 200, 200));
2767
2768 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2769
2770 constexpr int32_t touchDeviceId = 4;
2771 constexpr int32_t stylusDeviceId = 2;
2772
2773 // Touch down on window
2774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2775 .deviceId(touchDeviceId)
2776 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2777 .build());
2778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2779 .deviceId(touchDeviceId)
2780 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2781 .build());
2782 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2783 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2784
2785 // Stylus down on the window
2786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2787 .deviceId(stylusDeviceId)
2788 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2789 .build());
2790 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2791 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2792
2793 // Subsequent stylus movements are delivered correctly
2794 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2795 .deviceId(stylusDeviceId)
2796 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2797 .build());
2798 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2799 WithCoords(101, 111)));
2800}
2801
2802/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002803 * Two windows: a window on the left and a window on the right.
2804 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2805 * down. Then, on the left window, also place second touch pointer down.
2806 * This test tries to reproduce a crash.
2807 * In the buggy implementation, second pointer down on the left window would cause a crash.
2808 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002809TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2811 sp<FakeWindowHandle> leftWindow =
2812 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2813 leftWindow->setFrame(Rect(0, 0, 200, 200));
2814
2815 sp<FakeWindowHandle> rightWindow =
2816 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2817 rightWindow->setFrame(Rect(200, 0, 400, 200));
2818
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002819 mDispatcher->onWindowInfosChanged(
2820 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002821
2822 const int32_t touchDeviceId = 4;
2823 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002824
2825 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2827 .deviceId(mouseDeviceId)
2828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2829 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002830 leftWindow->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2832
2833 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2835 .deviceId(mouseDeviceId)
2836 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2837 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2838 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002839
2840 leftWindow->consumeMotionEvent(
2841 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2842 leftWindow->consumeMotionEvent(
2843 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2844
Prabir Pradhan678438e2023-04-13 19:32:51 +00002845 mDispatcher->notifyMotion(
2846 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2847 .deviceId(mouseDeviceId)
2848 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2849 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2850 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2851 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2853
2854 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2856 .deviceId(touchDeviceId)
2857 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2858 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002859 leftWindow->assertNoEvents();
2860
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002861 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2862
2863 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002864 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2865 .deviceId(touchDeviceId)
2866 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2867 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2868 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002869 // Since this is now a new splittable pointer going down on the left window, and it's coming
2870 // from a different device, the current gesture in the left window (pointer down) should first
2871 // be canceled.
2872 leftWindow->consumeMotionEvent(
2873 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002874 leftWindow->consumeMotionEvent(
2875 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2876 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2877 // current implementation.
2878 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2879 rightWindow->consumeMotionEvent(
2880 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2881
2882 leftWindow->assertNoEvents();
2883 rightWindow->assertNoEvents();
2884}
2885
2886/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002887 * Two windows: a window on the left and a window on the right.
2888 * Mouse is hovered on the left window and stylus is hovered on the right window.
2889 */
2890TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2892 sp<FakeWindowHandle> leftWindow =
2893 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2894 leftWindow->setFrame(Rect(0, 0, 200, 200));
2895
2896 sp<FakeWindowHandle> rightWindow =
2897 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2898 rightWindow->setFrame(Rect(200, 0, 400, 200));
2899
2900 mDispatcher->onWindowInfosChanged(
2901 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2902
2903 const int32_t stylusDeviceId = 3;
2904 const int32_t mouseDeviceId = 6;
2905
2906 // Start hovering over the left window
2907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2908 .deviceId(mouseDeviceId)
2909 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2910 .build());
2911 leftWindow->consumeMotionEvent(
2912 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2913
2914 // Stylus hovered on right window
2915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2916 .deviceId(stylusDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2918 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002919 rightWindow->consumeMotionEvent(
2920 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2921
2922 // Subsequent HOVER_MOVE events are dispatched correctly.
2923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2924 .deviceId(mouseDeviceId)
2925 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2926 .build());
2927 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002928 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002929
2930 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2931 .deviceId(stylusDeviceId)
2932 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2933 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002934 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002935 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002936
2937 leftWindow->assertNoEvents();
2938 rightWindow->assertNoEvents();
2939}
2940
2941/**
2942 * Three windows: a window on the left and a window on the right.
2943 * And a spy window that's positioned above all of them.
2944 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2945 * Check the stream that's received by the spy.
2946 */
2947TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2949
2950 sp<FakeWindowHandle> spyWindow =
2951 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2952 spyWindow->setFrame(Rect(0, 0, 400, 400));
2953 spyWindow->setTrustedOverlay(true);
2954 spyWindow->setSpy(true);
2955
2956 sp<FakeWindowHandle> leftWindow =
2957 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2958 leftWindow->setFrame(Rect(0, 0, 200, 200));
2959
2960 sp<FakeWindowHandle> rightWindow =
2961 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2962
2963 rightWindow->setFrame(Rect(200, 0, 400, 200));
2964
2965 mDispatcher->onWindowInfosChanged(
2966 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2967
2968 const int32_t stylusDeviceId = 1;
2969 const int32_t touchDeviceId = 2;
2970
2971 // Stylus down on the left window
2972 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2973 .deviceId(stylusDeviceId)
2974 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2975 .build());
2976 leftWindow->consumeMotionEvent(
2977 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2978 spyWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2980
2981 // Touch down on the right window
2982 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2983 .deviceId(touchDeviceId)
2984 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2985 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002986 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002987 rightWindow->consumeMotionEvent(
2988 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002989
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002990 // Spy window does not receive touch events, because stylus events take precedence, and it
2991 // already has an active stylus gesture.
2992
2993 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002994 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2995 .deviceId(stylusDeviceId)
2996 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2997 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002998 leftWindow->consumeMotionEvent(
2999 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3000 spyWindow->consumeMotionEvent(
3001 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003002
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003003 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3005 .deviceId(touchDeviceId)
3006 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3007 .build());
3008 rightWindow->consumeMotionEvent(
3009 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003010
3011 spyWindow->assertNoEvents();
3012 leftWindow->assertNoEvents();
3013 rightWindow->assertNoEvents();
3014}
3015
3016/**
3017 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3018 * both.
3019 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003020 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003021 * At the same time, left and right should be getting independent streams of hovering and touch,
3022 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003023 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003024TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3026
3027 sp<FakeWindowHandle> spyWindow =
3028 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3029 spyWindow->setFrame(Rect(0, 0, 400, 400));
3030 spyWindow->setTrustedOverlay(true);
3031 spyWindow->setSpy(true);
3032
3033 sp<FakeWindowHandle> leftWindow =
3034 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3035 leftWindow->setFrame(Rect(0, 0, 200, 200));
3036
3037 sp<FakeWindowHandle> rightWindow =
3038 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3039 rightWindow->setFrame(Rect(200, 0, 400, 200));
3040
3041 mDispatcher->onWindowInfosChanged(
3042 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3043
3044 const int32_t stylusDeviceId = 1;
3045 const int32_t touchDeviceId = 2;
3046
3047 // Stylus hover on the left window
3048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3049 .deviceId(stylusDeviceId)
3050 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3051 .build());
3052 leftWindow->consumeMotionEvent(
3053 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3054 spyWindow->consumeMotionEvent(
3055 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3056
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003057 // Touch down on the right window. Spy doesn't receive this touch because it already has
3058 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003059 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3060 .deviceId(touchDeviceId)
3061 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3062 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003063 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003064 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003065 rightWindow->consumeMotionEvent(
3066 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3067
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003068 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3070 .deviceId(stylusDeviceId)
3071 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3072 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003073 leftWindow->consumeMotionEvent(
3074 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003075 spyWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003077
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003078 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3080 .deviceId(touchDeviceId)
3081 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3082 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003083 rightWindow->consumeMotionEvent(
3084 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3085
3086 spyWindow->assertNoEvents();
3087 leftWindow->assertNoEvents();
3088 rightWindow->assertNoEvents();
3089}
3090
3091/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003092 * On a single window, use two different devices: mouse and touch.
3093 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3094 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3095 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3096 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3097 * represent a new gesture.
3098 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003099TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3101 sp<FakeWindowHandle> window =
3102 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3103 window->setFrame(Rect(0, 0, 400, 400));
3104
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003105 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106
3107 const int32_t touchDeviceId = 4;
3108 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003109
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003110 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3112 .deviceId(touchDeviceId)
3113 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3114 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003116 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3117 .deviceId(touchDeviceId)
3118 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3119 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3120 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003121 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003122 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3123 .deviceId(touchDeviceId)
3124 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3125 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3126 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3128 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3129 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3130
3131 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3133 .deviceId(mouseDeviceId)
3134 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3135 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3136 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003137
3138 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003139 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003140 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3141
Prabir Pradhan678438e2023-04-13 19:32:51 +00003142 mDispatcher->notifyMotion(
3143 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3144 .deviceId(mouseDeviceId)
3145 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3146 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3147 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3148 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003149 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3150
3151 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003152 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3153 .deviceId(touchDeviceId)
3154 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3155 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3156 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003157 // Since we already canceled this touch gesture, it will be ignored until a completely new
3158 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3159 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3160 // However, mouse movements should continue to work.
3161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3162 .deviceId(mouseDeviceId)
3163 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3164 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3165 .build());
3166 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3167
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003168 window->assertNoEvents();
3169}
3170
3171/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003172 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3173 * the injected event.
3174 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003175TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3177 sp<FakeWindowHandle> window =
3178 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3179 window->setFrame(Rect(0, 0, 400, 400));
3180
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003181 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003182
3183 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003184 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3185 // completion.
3186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003187 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003188 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3189 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003190 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003191 .build()));
3192 window->consumeMotionEvent(
3193 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3194
3195 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3196 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003197 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3198 .deviceId(touchDeviceId)
3199 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3200 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003201
3202 window->consumeMotionEvent(
3203 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3204 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3205}
3206
3207/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003208 * This test is similar to the test above, but the sequence of injected events is different.
3209 *
3210 * Two windows: a window on the left and a window on the right.
3211 * Mouse is hovered over the left window.
3212 * Next, we tap on the left window, where the cursor was last seen.
3213 *
3214 * After that, we inject one finger down onto the right window, and then a second finger down onto
3215 * the left window.
3216 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3217 * window (first), and then another on the left window (second).
3218 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3219 * In the buggy implementation, second finger down on the left window would cause a crash.
3220 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003221TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3223 sp<FakeWindowHandle> leftWindow =
3224 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3225 leftWindow->setFrame(Rect(0, 0, 200, 200));
3226
3227 sp<FakeWindowHandle> rightWindow =
3228 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3229 rightWindow->setFrame(Rect(200, 0, 400, 200));
3230
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003231 mDispatcher->onWindowInfosChanged(
3232 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003233
3234 const int32_t mouseDeviceId = 6;
3235 const int32_t touchDeviceId = 4;
3236 // Hover over the left window. Keep the cursor there.
3237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003238 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003239 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3240 AINPUT_SOURCE_MOUSE)
3241 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003243 .build()));
3244 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3245
3246 // Tap on left window
3247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003248 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003249 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3250 AINPUT_SOURCE_TOUCHSCREEN)
3251 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003252 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003253 .build()));
3254
3255 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003256 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003257 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3258 AINPUT_SOURCE_TOUCHSCREEN)
3259 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003260 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003261 .build()));
3262 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3263 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3264 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3265
3266 // First finger down on right window
3267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003268 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003269 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3270 AINPUT_SOURCE_TOUCHSCREEN)
3271 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003272 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003273 .build()));
3274 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3275
3276 // Second finger down on the left window
3277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003278 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003279 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3280 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003281 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3282 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003283 .build()));
3284 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3285 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3286
3287 // No more events
3288 leftWindow->assertNoEvents();
3289 rightWindow->assertNoEvents();
3290}
3291
3292/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003293 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3294 * While the touch is down, new hover events from the stylus device should be ignored. After the
3295 * touch is gone, stylus hovering should start working again.
3296 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003297TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3299 sp<FakeWindowHandle> window =
3300 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3301 window->setFrame(Rect(0, 0, 200, 200));
3302
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003303 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003304
3305 const int32_t stylusDeviceId = 5;
3306 const int32_t touchDeviceId = 4;
3307 // Start hovering with stylus
3308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003309 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003310 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003311 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003313 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003314 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003315
3316 // Finger down on the window
3317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003318 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003319 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003320 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003321 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003322 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003323 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003324
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003325 // Continue hovering with stylus.
3326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003327 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003328 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3329 AINPUT_SOURCE_STYLUS)
3330 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003332 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003333 // Hovers continue to work
3334 window->consumeMotionEvent(
3335 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003336
3337 // Lift up the finger
3338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003340 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3341 AINPUT_SOURCE_TOUCHSCREEN)
3342 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003343 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003344 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003345
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003348 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3349 AINPUT_SOURCE_STYLUS)
3350 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003351 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003352 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003353 window->consumeMotionEvent(
3354 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003355 window->assertNoEvents();
3356}
3357
3358/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003359 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3360 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3361 *
3362 * Two windows: one on the left and one on the right.
3363 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3364 * Stylus down on the left window, and then touch down on the right window.
3365 * Check that the right window doesn't get touches while the stylus is down on the left window.
3366 */
3367TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3369 sp<FakeWindowHandle> leftWindow =
3370 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3371 ADISPLAY_ID_DEFAULT);
3372 leftWindow->setFrame(Rect(0, 0, 100, 100));
3373
3374 sp<FakeWindowHandle> sbtRightWindow =
3375 sp<FakeWindowHandle>::make(application, mDispatcher,
3376 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3377 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3378 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3379
3380 mDispatcher->onWindowInfosChanged(
3381 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3382
3383 const int32_t stylusDeviceId = 5;
3384 const int32_t touchDeviceId = 4;
3385
3386 // Stylus down in the left window
3387 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3388 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3389 .deviceId(stylusDeviceId)
3390 .build());
3391 leftWindow->consumeMotionEvent(
3392 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3393
3394 // Finger tap on the right window
3395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3396 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3397 .deviceId(touchDeviceId)
3398 .build());
3399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3400 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3401 .deviceId(touchDeviceId)
3402 .build());
3403
3404 // The touch should be blocked, because stylus is down somewhere else on screen!
3405 sbtRightWindow->assertNoEvents();
3406
3407 // Continue stylus motion, and ensure it's not impacted.
3408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3409 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3410 .deviceId(stylusDeviceId)
3411 .build());
3412 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3413 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3414 .deviceId(stylusDeviceId)
3415 .build());
3416 leftWindow->consumeMotionEvent(
3417 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3418 leftWindow->consumeMotionEvent(
3419 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3420
3421 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3423 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3424 .deviceId(touchDeviceId)
3425 .build());
3426 sbtRightWindow->consumeMotionEvent(
3427 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3428}
3429
3430/**
3431 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3432 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3433 *
3434 * Two windows: one on the left and one on the right.
3435 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3436 * Stylus hover on the left window, and then touch down on the right window.
3437 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3438 */
3439TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3441 sp<FakeWindowHandle> leftWindow =
3442 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3443 ADISPLAY_ID_DEFAULT);
3444 leftWindow->setFrame(Rect(0, 0, 100, 100));
3445
3446 sp<FakeWindowHandle> sbtRightWindow =
3447 sp<FakeWindowHandle>::make(application, mDispatcher,
3448 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3449 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3450 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3451
3452 mDispatcher->onWindowInfosChanged(
3453 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3454
3455 const int32_t stylusDeviceId = 5;
3456 const int32_t touchDeviceId = 4;
3457
3458 // Stylus hover in the left window
3459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3460 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3461 .deviceId(stylusDeviceId)
3462 .build());
3463 leftWindow->consumeMotionEvent(
3464 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3465
3466 // Finger tap on the right window
3467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3468 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3469 .deviceId(touchDeviceId)
3470 .build());
3471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3472 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3473 .deviceId(touchDeviceId)
3474 .build());
3475
3476 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3477 sbtRightWindow->assertNoEvents();
3478
3479 // Continue stylus motion, and ensure it's not impacted.
3480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3482 .deviceId(stylusDeviceId)
3483 .build());
3484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3485 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3486 .deviceId(stylusDeviceId)
3487 .build());
3488 leftWindow->consumeMotionEvent(
3489 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3490 leftWindow->consumeMotionEvent(
3491 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3492
3493 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3494 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3495 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3496 .deviceId(touchDeviceId)
3497 .build());
3498 sbtRightWindow->consumeMotionEvent(
3499 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3500}
3501
3502/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003503 * A spy window above a window with no input channel.
3504 * Start hovering with a stylus device, and then tap with it.
3505 * Ensure spy window receives the entire sequence.
3506 */
3507TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3509 sp<FakeWindowHandle> spyWindow =
3510 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3511 spyWindow->setFrame(Rect(0, 0, 200, 200));
3512 spyWindow->setTrustedOverlay(true);
3513 spyWindow->setSpy(true);
3514 sp<FakeWindowHandle> window =
3515 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3516 window->setNoInputChannel(true);
3517 window->setFrame(Rect(0, 0, 200, 200));
3518
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003519 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003520
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003521 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3523 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3524 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003525 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3526 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3528 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3529 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003530 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3531
3532 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3534 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3535 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003536 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3537
3538 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3540 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3541 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003542 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3543
3544 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3546 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3547 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003548 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3549 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3551 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3552 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003553 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3554
3555 // No more events
3556 spyWindow->assertNoEvents();
3557 window->assertNoEvents();
3558}
3559
3560/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003561 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3562 * rejected. But since we already have an ongoing gesture, this event should be processed.
3563 * This prevents inconsistent events being handled inside the dispatcher.
3564 */
3565TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3567
3568 sp<FakeWindowHandle> window =
3569 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3570 window->setFrame(Rect(0, 0, 200, 200));
3571
3572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3573
3574 // Start hovering with stylus
3575 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3576 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3577 .build());
3578 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3579
3580 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3581 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3582 .build();
3583 // Make this 'hoverExit' event stale
3584 mFakePolicy->setStaleEventTimeout(100ms);
3585 std::this_thread::sleep_for(100ms);
3586
3587 // It shouldn't be dropped by the dispatcher, even though it's stale.
3588 mDispatcher->notifyMotion(hoverExit);
3589 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3590
3591 // Stylus starts hovering again! There should be no crash.
3592 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3593 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3594 .build());
3595 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3596}
3597
3598/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003599 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3600 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3601 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3602 * While the mouse is down, new move events from the touch device should be ignored.
3603 */
3604TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3606 sp<FakeWindowHandle> spyWindow =
3607 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3608 spyWindow->setFrame(Rect(0, 0, 200, 200));
3609 spyWindow->setTrustedOverlay(true);
3610 spyWindow->setSpy(true);
3611 sp<FakeWindowHandle> window =
3612 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3613 window->setFrame(Rect(0, 0, 200, 200));
3614
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003615 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003616
3617 const int32_t mouseDeviceId = 7;
3618 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003619
3620 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3622 .deviceId(mouseDeviceId)
3623 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3624 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003625 spyWindow->consumeMotionEvent(
3626 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3627 window->consumeMotionEvent(
3628 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3629
3630 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3632 .deviceId(touchDeviceId)
3633 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3636 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3637 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3638 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3639
Prabir Pradhan678438e2023-04-13 19:32:51 +00003640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3641 .deviceId(touchDeviceId)
3642 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3643 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003644 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3645 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3646
3647 // Pilfer the stream
3648 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3649 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3650
Prabir Pradhan678438e2023-04-13 19:32:51 +00003651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3652 .deviceId(touchDeviceId)
3653 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3654 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003655 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3656
3657 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3659 .deviceId(mouseDeviceId)
3660 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3661 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3662 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003663
3664 spyWindow->consumeMotionEvent(
3665 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3666 spyWindow->consumeMotionEvent(
3667 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3668 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3669
Prabir Pradhan678438e2023-04-13 19:32:51 +00003670 mDispatcher->notifyMotion(
3671 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3672 .deviceId(mouseDeviceId)
3673 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3674 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003677 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3678 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3679
3680 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3682 .deviceId(mouseDeviceId)
3683 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3684 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3685 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003686 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3687 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3688
3689 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3691 .deviceId(touchDeviceId)
3692 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3693 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003694
3695 // No more events
3696 spyWindow->assertNoEvents();
3697 window->assertNoEvents();
3698}
3699
3700/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003701 * On the display, have a single window, and also an area where there's no window.
3702 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3703 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3704 */
3705TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3707 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003708 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003709
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003711
3712 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003713 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003714
3715 mDispatcher->waitForIdle();
3716 window->assertNoEvents();
3717
3718 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003719 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003720 mDispatcher->waitForIdle();
3721 window->consumeMotionDown();
3722}
3723
3724/**
3725 * Same test as above, but instead of touching the empty space, the first touch goes to
3726 * non-touchable window.
3727 */
3728TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3730 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003731 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003732 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3733 window1->setTouchable(false);
3734 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003735 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003736 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3737
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003738 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003739
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003740 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003741 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003742
3743 mDispatcher->waitForIdle();
3744 window1->assertNoEvents();
3745 window2->assertNoEvents();
3746
3747 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003748 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003749 mDispatcher->waitForIdle();
3750 window2->consumeMotionDown();
3751}
3752
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003753/**
3754 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3755 * to the event time of the first ACTION_DOWN sent to the particular window.
3756 */
3757TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3758 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3759 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003760 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003761 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3762 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003763 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003764 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3765
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003766 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003767
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003768 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003770
3771 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003772
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003773 std::unique_ptr<MotionEvent> motionEvent1 = window1->consumeMotionEvent();
3774 ASSERT_NE(nullptr, motionEvent1);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003775 window2->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003776 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3777 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003778
3779 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003781 mDispatcher->waitForIdle();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003782 std::unique_ptr<MotionEvent> motionEvent2 = window2->consumeMotionEvent();
3783 ASSERT_NE(nullptr, motionEvent2);
3784 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003785 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003786 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003787
3788 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003790 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003791 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003792
3793 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003794 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003795 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003796 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003797
3798 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3799 window1->consumeMotionMove();
3800 window1->assertNoEvents();
3801
3802 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003803 mDispatcher->notifyMotion(
3804 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003805 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003806 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003807
Prabir Pradhan678438e2023-04-13 19:32:51 +00003808 mDispatcher->notifyMotion(
3809 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003810 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003811 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003812}
3813
Garfield Tandf26e862020-07-01 20:18:19 -07003814TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003816 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003817 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003818 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003819 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003820 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003821 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003822
3823 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3824
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003825 mDispatcher->onWindowInfosChanged(
3826 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003827
3828 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003830 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003831 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3832 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003833 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003834 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003835 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003836
3837 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003839 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003840 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3841 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003842 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003843 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003844 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3845 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003846
3847 // Inject a series of mouse events for a mouse click
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_DOWN, AINPUT_SOURCE_MOUSE)
3851 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003852 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003853 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003854 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3855 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003856
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_BUTTON_PRESS,
3860 AINPUT_SOURCE_MOUSE)
3861 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3862 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003863 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003864 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003865 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003866
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_BUTTON_RELEASE,
3870 AINPUT_SOURCE_MOUSE)
3871 .buttonState(0)
3872 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003873 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003874 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003875 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003876
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003878 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003879 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3880 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003881 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003882 .build()));
3883 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3884
3885 // Move mouse cursor back to right window
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_HOVER_MOVE,
3889 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003890 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003891 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003892 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003893
3894 // No more events
3895 windowLeft->assertNoEvents();
3896 windowRight->assertNoEvents();
3897}
3898
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003899/**
3900 * Put two fingers down (and don't release them) and click the mouse button.
3901 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3902 * currently active gesture should be canceled, and the new one should proceed.
3903 */
3904TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3906 sp<FakeWindowHandle> window =
3907 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3908 window->setFrame(Rect(0, 0, 600, 800));
3909
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003910 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003911
3912 const int32_t touchDeviceId = 4;
3913 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003914
3915 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3917 .deviceId(touchDeviceId)
3918 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3919 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003920
Prabir Pradhan678438e2023-04-13 19:32:51 +00003921 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3922 .deviceId(touchDeviceId)
3923 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3924 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3925 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003926 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3927 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3928
3929 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003930 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3931 .deviceId(mouseDeviceId)
3932 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3934 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3936 WithPointerCount(2u)));
3937 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3938
Prabir Pradhan678438e2023-04-13 19:32:51 +00003939 mDispatcher->notifyMotion(
3940 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3941 .deviceId(mouseDeviceId)
3942 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3943 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3944 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3945 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003946 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3947
3948 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3949 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003950 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3951 .deviceId(touchDeviceId)
3952 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3953 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3954 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003955 window->assertNoEvents();
3956}
3957
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003958TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3960
3961 sp<FakeWindowHandle> spyWindow =
3962 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3963 spyWindow->setFrame(Rect(0, 0, 600, 800));
3964 spyWindow->setTrustedOverlay(true);
3965 spyWindow->setSpy(true);
3966 sp<FakeWindowHandle> window =
3967 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3968 window->setFrame(Rect(0, 0, 600, 800));
3969
3970 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003971 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003972
3973 // Send mouse cursor to the window
3974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003975 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003976 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3977 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003978 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003979 .build()));
3980
3981 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3982 WithSource(AINPUT_SOURCE_MOUSE)));
3983 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3984 WithSource(AINPUT_SOURCE_MOUSE)));
3985
3986 window->assertNoEvents();
3987 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003988}
3989
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003990TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3992
3993 sp<FakeWindowHandle> spyWindow =
3994 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3995 spyWindow->setFrame(Rect(0, 0, 600, 800));
3996 spyWindow->setTrustedOverlay(true);
3997 spyWindow->setSpy(true);
3998 sp<FakeWindowHandle> window =
3999 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4000 window->setFrame(Rect(0, 0, 600, 800));
4001
4002 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004003 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004004
4005 // Send mouse cursor to the window
4006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004007 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004008 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4009 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004010 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004011 .build()));
4012
4013 // Move mouse cursor
4014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004015 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004016 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4017 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004018 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004019 .build()));
4020
4021 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4022 WithSource(AINPUT_SOURCE_MOUSE)));
4023 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4024 WithSource(AINPUT_SOURCE_MOUSE)));
4025 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4026 WithSource(AINPUT_SOURCE_MOUSE)));
4027 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4028 WithSource(AINPUT_SOURCE_MOUSE)));
4029 // Touch down on the window
4030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004031 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004032 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4033 AINPUT_SOURCE_TOUCHSCREEN)
4034 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004035 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004036 .build()));
4037 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4038 WithSource(AINPUT_SOURCE_MOUSE)));
4039 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4040 WithSource(AINPUT_SOURCE_MOUSE)));
4041 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4042 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4043 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4044 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4045
4046 // pilfer the motion, retaining the gesture on the spy window.
4047 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4048 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4049 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4050
4051 // Touch UP on the window
4052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004053 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004054 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4055 AINPUT_SOURCE_TOUCHSCREEN)
4056 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004057 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004058 .build()));
4059 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4060 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4061
4062 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4063 // to send a new gesture. It should again go to both windows (spy and the window below), just
4064 // like the first gesture did, before pilfering. The window configuration has not changed.
4065
4066 // One more tap - DOWN
4067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004068 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004069 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4070 AINPUT_SOURCE_TOUCHSCREEN)
4071 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004072 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004073 .build()));
4074 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4075 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4076 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4077 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4078
4079 // Touch UP on the window
4080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004081 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004082 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4083 AINPUT_SOURCE_TOUCHSCREEN)
4084 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004085 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004086 .build()));
4087 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4088 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4089 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4090 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4091
4092 window->assertNoEvents();
4093 spyWindow->assertNoEvents();
4094}
4095
Garfield Tandf26e862020-07-01 20:18:19 -07004096// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4097// directly in this test.
4098TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004100 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004101 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004102 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004103
4104 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4105
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004106 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004107
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004109 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004110 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4111 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004112 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004113 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004114 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004115 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004117 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004118 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4119 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004121 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004122 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4123 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004124
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004126 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004127 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4128 AINPUT_SOURCE_MOUSE)
4129 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4130 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
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_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004134
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_BUTTON_RELEASE,
4138 AINPUT_SOURCE_MOUSE)
4139 .buttonState(0)
4140 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004141 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004142 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004143 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004144
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004146 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004147 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4148 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004149 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004150 .build()));
4151 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4152
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004153 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4154 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4155 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004156 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004157 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4158 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004159 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004160 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004161 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004162}
4163
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004164/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004165 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4166 * is generated.
4167 */
4168TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4170 sp<FakeWindowHandle> window =
4171 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4172 window->setFrame(Rect(0, 0, 1200, 800));
4173
4174 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4175
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004177
4178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004179 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004180 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4181 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004182 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004183 .build()));
4184 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4185
4186 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004187 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004188 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4189}
4190
4191/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004192 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4193 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004194TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4195 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4196 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004197 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4198 sp<FakeWindowHandle> window =
4199 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4200 window->setFrame(Rect(0, 0, 1200, 800));
4201
4202 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4203
4204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4205
4206 MotionEventBuilder hoverEnterBuilder =
4207 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4208 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4209 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4211 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4213 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4214 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4215 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4216}
4217
4218/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004219 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4220 */
4221TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4223 sp<FakeWindowHandle> window =
4224 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4225 window->setFrame(Rect(0, 0, 100, 100));
4226
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004227 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004228
4229 const int32_t mouseDeviceId = 7;
4230 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004231
4232 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4234 .deviceId(mouseDeviceId)
4235 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4236 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004237 window->consumeMotionEvent(
4238 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4239
4240 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004241 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4242 .deviceId(touchDeviceId)
4243 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4244 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004245
4246 window->consumeMotionEvent(
4247 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4248 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4249}
4250
4251/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004252 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004253 * The tap causes a HOVER_EXIT event to be generated because the current event
4254 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004255 */
4256TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4258 sp<FakeWindowHandle> window =
4259 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4260 window->setFrame(Rect(0, 0, 100, 100));
4261
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004262 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4264 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4265 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004266 ASSERT_NO_FATAL_FAILURE(
4267 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4268 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004269
4270 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4273 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004274 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004275 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4276 WithSource(AINPUT_SOURCE_MOUSE))));
4277
4278 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004279 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4280 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4281
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004282 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4283 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4284 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004285 ASSERT_NO_FATAL_FAILURE(
4286 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4287 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4288}
4289
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004290TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4291 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4292 sp<FakeWindowHandle> windowDefaultDisplay =
4293 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4294 ADISPLAY_ID_DEFAULT);
4295 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4296 sp<FakeWindowHandle> windowSecondDisplay =
4297 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4298 SECOND_DISPLAY_ID);
4299 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4300
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004301 mDispatcher->onWindowInfosChanged(
4302 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004303
4304 // Set cursor position in window in default display and check that hover enter and move
4305 // events are generated.
4306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004307 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004308 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4309 AINPUT_SOURCE_MOUSE)
4310 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004311 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004312 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004313 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004314
4315 // Remove all windows in secondary display and check that no event happens on window in
4316 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004317 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4318
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004319 windowDefaultDisplay->assertNoEvents();
4320
4321 // Move cursor position in window in default display and check that only hover move
4322 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004323 mDispatcher->onWindowInfosChanged(
4324 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004325 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(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004331 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004332 windowDefaultDisplay->consumeMotionEvent(
4333 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4334 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004335 windowDefaultDisplay->assertNoEvents();
4336}
4337
Garfield Tan00f511d2019-06-12 16:55:40 -07004338TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004339 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004340
4341 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004342 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004343 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004344 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004345 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004346 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004347
4348 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4349
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004350 mDispatcher->onWindowInfosChanged(
4351 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004352
4353 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4354 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004356 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004357 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004358 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004359 windowRight->assertNoEvents();
4360}
4361
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004362TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004364 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4365 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004366 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004367
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004368 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004369 setFocusedWindow(window);
4370
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004371 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004372
Prabir Pradhan678438e2023-04-13 19:32:51 +00004373 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004374
4375 // Window should receive key down event.
4376 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4377
4378 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4379 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004381 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004382}
4383
4384TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004386 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4387 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004388
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004389 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004390
Prabir Pradhan678438e2023-04-13 19:32:51 +00004391 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4392 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004393
4394 // Window should receive motion down event.
4395 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4396
4397 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4398 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004399 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004400 window->consumeMotionEvent(
4401 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004402}
4403
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004404TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4406 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4407 "Fake Window", ADISPLAY_ID_DEFAULT);
4408
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004409 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004410
4411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4412 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4413 .build());
4414
4415 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4416
4417 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4418 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4419 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4420
4421 // After the device has been reset, a new hovering stream can be sent to the window
4422 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4424 .build());
4425 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4426}
4427
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004428TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004430 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4431 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004432 window->setFocusable(true);
4433
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004434 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004435 setFocusedWindow(window);
4436
4437 window->consumeFocusEvent(true);
4438
Prabir Pradhan678438e2023-04-13 19:32:51 +00004439 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004440 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4441 const nsecs_t injectTime = keyArgs.eventTime;
4442 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004443 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004444 // The dispatching time should be always greater than or equal to intercept key timeout.
4445 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4446 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4447 std::chrono::nanoseconds(interceptKeyTimeout).count());
4448}
4449
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004450/**
4451 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4452 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004453TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004455 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4456 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004457 window->setFocusable(true);
4458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004460 setFocusedWindow(window);
4461
4462 window->consumeFocusEvent(true);
4463
Prabir Pradhan678438e2023-04-13 19:32:51 +00004464 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004465 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004466
4467 // Set a value that's significantly larger than the default consumption timeout. If the
4468 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4469 mFakePolicy->setInterceptKeyTimeout(600ms);
4470 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4471 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004472 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4473}
4474
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004475/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004476 * Two windows. First is a regular window. Second does not overlap with the first, and has
4477 * WATCH_OUTSIDE_TOUCH.
4478 * Both windows are owned by the same UID.
4479 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4480 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4481 */
4482TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4483 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004484 sp<FakeWindowHandle> window =
4485 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004486 window->setFrame(Rect{0, 0, 100, 100});
4487
4488 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004489 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004490 ADISPLAY_ID_DEFAULT);
4491 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4492 outsideWindow->setWatchOutsideTouch(true);
4493 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004494 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004495
4496 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004497 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4498 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4499 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004500 window->consumeMotionDown();
4501 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4502 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4503 outsideWindow->consumeMotionEvent(
4504 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004505
4506 // Ensure outsideWindow doesn't get any more events for the gesture.
4507 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4508 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4509 window->consumeMotionMove();
4510 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004511}
4512
4513/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004514 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4515 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4516 * ACTION_OUTSIDE event is sent per gesture.
4517 */
4518TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4519 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004521 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4522 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004523 window->setWatchOutsideTouch(true);
4524 window->setFrame(Rect{0, 0, 100, 100});
4525 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004526 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4527 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004528 secondWindow->setFrame(Rect{100, 100, 200, 200});
4529 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004530 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4531 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004532 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004533 mDispatcher->onWindowInfosChanged(
4534 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004535
4536 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4538 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4539 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004540 window->assertNoEvents();
4541 secondWindow->assertNoEvents();
4542
4543 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4544 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004545 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4546 ADISPLAY_ID_DEFAULT,
4547 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004548 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4549 window->consumeMotionEvent(
4550 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004551 secondWindow->consumeMotionDown();
4552 thirdWindow->assertNoEvents();
4553
4554 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4555 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004556 mDispatcher->notifyMotion(
4557 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4558 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004559 window->assertNoEvents();
4560 secondWindow->consumeMotionMove();
4561 thirdWindow->consumeMotionDown();
4562}
4563
Prabir Pradhan814fe082022-07-22 20:22:18 +00004564TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004566 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4567 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004568 window->setFocusable(true);
4569
Patrick Williamsd828f302023-04-28 17:52:08 -05004570 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004571 setFocusedWindow(window);
4572
4573 window->consumeFocusEvent(true);
4574
Prabir Pradhan678438e2023-04-13 19:32:51 +00004575 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4576 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4577 mDispatcher->notifyKey(keyDown);
4578 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004579
4580 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4581 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4582
4583 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004584 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004585
4586 window->consumeFocusEvent(false);
4587
Prabir Pradhan678438e2023-04-13 19:32:51 +00004588 mDispatcher->notifyKey(keyDown);
4589 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004590 window->assertNoEvents();
4591}
4592
Arthur Hung96483742022-11-15 03:30:48 +00004593TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4595 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4596 "Fake Window", ADISPLAY_ID_DEFAULT);
4597 // Ensure window is non-split and have some transform.
4598 window->setPreventSplitting(true);
4599 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004600 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004601
4602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004603 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004604 {50, 50}))
4605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4606 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4607
4608 const MotionEvent secondFingerDownEvent =
4609 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4610 .displayId(ADISPLAY_ID_DEFAULT)
4611 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004612 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4613 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004614 .build();
4615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004616 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004617 InputEventInjectionSync::WAIT_FOR_RESULT))
4618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4619
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004620 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4621 ASSERT_NE(nullptr, event);
4622 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4623 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4624 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4625 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4626 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004627}
4628
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004629/**
4630 * Two windows: a splittable and a non-splittable.
4631 * The non-splittable window shouldn't receive any "incomplete" gestures.
4632 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4633 * The second pointer should be dropped because the initial window is splittable, so it won't get
4634 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4635 * "incomplete" gestures.
4636 */
4637TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4639 sp<FakeWindowHandle> leftWindow =
4640 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4641 ADISPLAY_ID_DEFAULT);
4642 leftWindow->setPreventSplitting(false);
4643 leftWindow->setFrame(Rect(0, 0, 100, 100));
4644 sp<FakeWindowHandle> rightWindow =
4645 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4646 ADISPLAY_ID_DEFAULT);
4647 rightWindow->setPreventSplitting(true);
4648 rightWindow->setFrame(Rect(100, 100, 200, 200));
4649 mDispatcher->onWindowInfosChanged(
4650 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4651
4652 // Touch down on left, splittable window
4653 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4654 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4655 .build());
4656 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4657
4658 mDispatcher->notifyMotion(
4659 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4660 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4661 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4662 .build());
4663 leftWindow->assertNoEvents();
4664 rightWindow->assertNoEvents();
4665}
4666
Harry Cuttsb166c002023-05-09 13:06:05 +00004667TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4669 sp<FakeWindowHandle> window =
4670 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4671 window->setFrame(Rect(0, 0, 400, 400));
4672 sp<FakeWindowHandle> trustedOverlay =
4673 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4674 ADISPLAY_ID_DEFAULT);
4675 trustedOverlay->setSpy(true);
4676 trustedOverlay->setTrustedOverlay(true);
4677
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004678 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004679
4680 // Start a three-finger touchpad swipe
4681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4682 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4683 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4684 .build());
4685 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4686 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4687 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4688 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4689 .build());
4690 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4691 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4692 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4693 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4694 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4695 .build());
4696
4697 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4698 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4699 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4700
4701 // Move the swipe a bit
4702 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4703 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4704 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4705 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4706 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4707 .build());
4708
4709 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4710
4711 // End the swipe
4712 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4713 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4714 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4715 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4716 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4717 .build());
4718 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4719 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4720 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4721 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4722 .build());
4723 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4724 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4725 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4726 .build());
4727
4728 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4729 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4730 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4731
4732 window->assertNoEvents();
4733}
4734
4735TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4736 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4737 sp<FakeWindowHandle> window =
4738 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4739 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004740 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004741
4742 // Start a three-finger touchpad swipe
4743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4744 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4745 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4746 .build());
4747 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4748 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4749 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4750 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4751 .build());
4752 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4753 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4754 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4755 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4756 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4757 .build());
4758
4759 // Move the swipe a bit
4760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4761 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4762 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4763 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4764 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4765 .build());
4766
4767 // End the swipe
4768 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4769 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4770 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4771 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4772 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4773 .build());
4774 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4775 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4776 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4777 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4778 .build());
4779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4780 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4781 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4782 .build());
4783
4784 window->assertNoEvents();
4785}
4786
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004787/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004788 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4789 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004790 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004791 */
4792TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4794 sp<FakeWindowHandle> window =
4795 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4796 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004797 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004798
4799 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4800 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4801 .downTime(baseTime + 10)
4802 .eventTime(baseTime + 10)
4803 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4804 .build());
4805
4806 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4807
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004808 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004809 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004810
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004811 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004812
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004813 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4814 .downTime(baseTime + 10)
4815 .eventTime(baseTime + 30)
4816 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4817 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4818 .build());
4819
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004820 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4821
4822 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004823 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4824 .downTime(baseTime + 10)
4825 .eventTime(baseTime + 40)
4826 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4827 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4828 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004829
4830 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4831
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4833 .downTime(baseTime + 10)
4834 .eventTime(baseTime + 50)
4835 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4836 .build());
4837
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004838 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4839
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4841 .downTime(baseTime + 60)
4842 .eventTime(baseTime + 60)
4843 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4844 .build());
4845
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004846 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004847}
4848
4849/**
Hu Guo771a7692023-09-17 20:51:08 +08004850 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4851 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4852 * its coordinates should be converted by the transform of the windows of target screen.
4853 */
4854TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4855 // This case will create a window and a spy window on the default display and mirror
4856 // window on the second display. cancel event is sent through spy window pilferPointers
4857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4858
4859 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4860 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4861 spyWindowDefaultDisplay->setTrustedOverlay(true);
4862 spyWindowDefaultDisplay->setSpy(true);
4863
4864 sp<FakeWindowHandle> windowDefaultDisplay =
4865 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4866 ADISPLAY_ID_DEFAULT);
4867 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4868
4869 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4870 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4871
4872 // Add the windows to the dispatcher
4873 mDispatcher->onWindowInfosChanged(
4874 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4875 *windowSecondDisplay->getInfo()},
4876 {},
4877 0,
4878 0});
4879
4880 // Send down to ADISPLAY_ID_DEFAULT
4881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4882 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4883 {100, 100}))
4884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4885
4886 spyWindowDefaultDisplay->consumeMotionDown();
4887 windowDefaultDisplay->consumeMotionDown();
4888
4889 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4890
4891 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004892 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4893 ASSERT_NE(nullptr, event);
4894 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004895
4896 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4897 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4898 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4899 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004900 EXPECT_EQ(100, event->getX(0));
4901 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004902}
4903
4904/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004905 * Ensure the correct coordinate spaces are used by InputDispatcher.
4906 *
4907 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4908 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4909 * space.
4910 */
4911class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4912public:
4913 void SetUp() override {
4914 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004915 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004916 }
4917
4918 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4919 gui::DisplayInfo info;
4920 info.displayId = displayId;
4921 info.transform = transform;
4922 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004923 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004924 }
4925
4926 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4927 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004928 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004929 }
4930
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004931 void removeAllWindowsAndDisplays() {
4932 mDisplayInfos.clear();
4933 mWindowInfos.clear();
4934 }
4935
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004936 // Set up a test scenario where the display has a scaled projection and there are two windows
4937 // on the display.
4938 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4939 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4940 // respectively.
4941 ui::Transform displayTransform;
4942 displayTransform.set(2, 0, 0, 4);
4943 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4944
4945 std::shared_ptr<FakeApplicationHandle> application =
4946 std::make_shared<FakeApplicationHandle>();
4947
4948 // Add two windows to the display. Their frames are represented in the display space.
4949 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004950 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4951 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004952 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4953 addWindow(firstWindow);
4954
4955 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004956 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4957 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004958 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4959 addWindow(secondWindow);
4960 return {std::move(firstWindow), std::move(secondWindow)};
4961 }
4962
4963private:
4964 std::vector<gui::DisplayInfo> mDisplayInfos;
4965 std::vector<gui::WindowInfo> mWindowInfos;
4966};
4967
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004968TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004969 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4970 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004971 // selected so that if the hit test was performed with the point and the bounds being in
4972 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004973 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4974 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4975 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004976
4977 firstWindow->consumeMotionDown();
4978 secondWindow->assertNoEvents();
4979}
4980
4981// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4982// the event should be treated as being in the logical display space.
4983TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4984 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4985 // Send down to the first window. The point is represented in the logical display space. The
4986 // point is selected so that if the hit test was done in logical display space, then it would
4987 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004988 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004989 PointF{75 * 2, 55 * 4});
4990
4991 firstWindow->consumeMotionDown();
4992 secondWindow->assertNoEvents();
4993}
4994
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004995// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4996// event should be treated as being in the logical display space.
4997TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4998 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4999
5000 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5001 ui::Transform injectedEventTransform;
5002 injectedEventTransform.set(matrix);
5003 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5004 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5005
5006 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5007 .displayId(ADISPLAY_ID_DEFAULT)
5008 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005009 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005010 .x(untransformedPoint.x)
5011 .y(untransformedPoint.y))
5012 .build();
5013 event.transform(matrix);
5014
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005015 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005016 InputEventInjectionSync::WAIT_FOR_RESULT);
5017
5018 firstWindow->consumeMotionDown();
5019 secondWindow->assertNoEvents();
5020}
5021
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005022TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5023 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5024
5025 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005026 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5027 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5028 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005029
5030 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005031 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5032 ASSERT_NE(nullptr, event);
5033 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005034
5035 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005036 EXPECT_EQ(300, event->getRawX(0));
5037 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005038
5039 // Ensure that the x and y values are in the window's coordinate space.
5040 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5041 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005042 EXPECT_EQ(100, event->getX(0));
5043 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005044}
5045
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005046TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5047 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5048 // The monitor will always receive events in the logical display's coordinate space, because
5049 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005050 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005051
5052 // Send down to the first window.
5053 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5054 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5055 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5056 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5057
5058 // Second pointer goes down on second window.
5059 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5060 ADISPLAY_ID_DEFAULT,
5061 {PointF{50, 100}, PointF{150, 220}}));
5062 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5063 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5064 {1, PointF{300, 880}}};
5065 monitor.consumeMotionEvent(
5066 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5067
5068 mDispatcher->cancelCurrentTouch();
5069
5070 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5071 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5072 monitor.consumeMotionEvent(
5073 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5074}
5075
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005076TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5077 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5078
5079 // Send down to the first window.
5080 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5081 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5082 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5083
5084 // The pointer is transferred to the second window, and the second window receives it in the
5085 // correct coordinate space.
5086 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5087 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5088 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5089}
5090
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005091TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5092 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5093
5094 // Send hover move to the second window, and ensure it shows up as hover enter.
5095 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5096 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5097 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5098 WithCoords(100, 80), WithRawCoords(300, 880)));
5099
5100 // Touch down at the same location and ensure a hover exit is synthesized.
5101 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5102 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5103 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5104 WithRawCoords(300, 880)));
5105 secondWindow->consumeMotionEvent(
5106 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5107 secondWindow->assertNoEvents();
5108 firstWindow->assertNoEvents();
5109}
5110
Prabir Pradhan453ae732023-10-13 14:30:14 +00005111// Same as above, but while the window is being mirrored.
5112TEST_F(InputDispatcherDisplayProjectionTest,
5113 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5114 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5115
5116 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5117 ui::Transform secondDisplayTransform;
5118 secondDisplayTransform.set(matrix);
5119 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5120
5121 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5122 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5123 addWindow(secondWindowClone);
5124
5125 // Send hover move to the second window, and ensure it shows up as hover enter.
5126 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5127 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5128 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5129 WithCoords(100, 80), WithRawCoords(300, 880)));
5130
5131 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5132 // display.
5133 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5134 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5135 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5136 WithRawCoords(300, 880)));
5137 secondWindow->consumeMotionEvent(
5138 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5139 secondWindow->assertNoEvents();
5140 firstWindow->assertNoEvents();
5141}
5142
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005143TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5144 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5145
5146 // Send hover enter to second window
5147 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5148 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5149 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5150 WithCoords(100, 80), WithRawCoords(300, 880)));
5151
5152 mDispatcher->cancelCurrentTouch();
5153
5154 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5155 WithRawCoords(300, 880)));
5156 secondWindow->assertNoEvents();
5157 firstWindow->assertNoEvents();
5158}
5159
Prabir Pradhan453ae732023-10-13 14:30:14 +00005160// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005161TEST_F(InputDispatcherDisplayProjectionTest,
5162 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5163 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5164
5165 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5166 ui::Transform secondDisplayTransform;
5167 secondDisplayTransform.set(matrix);
5168 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5169
5170 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5171 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5172 addWindow(secondWindowClone);
5173
5174 // Send hover enter to second window
5175 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5176 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5177 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5178 WithCoords(100, 80), WithRawCoords(300, 880),
5179 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5180
5181 mDispatcher->cancelCurrentTouch();
5182
5183 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5184 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5185 WithRawCoords(300, 880),
5186 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5187 secondWindow->assertNoEvents();
5188 firstWindow->assertNoEvents();
5189}
5190
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005191/** Ensure consistent behavior of InputDispatcher in all orientations. */
5192class InputDispatcherDisplayOrientationFixture
5193 : public InputDispatcherDisplayProjectionTest,
5194 public ::testing::WithParamInterface<ui::Rotation> {};
5195
5196// This test verifies the touchable region of a window for all rotations of the display by tapping
5197// in different locations on the display, specifically points close to the four corners of a
5198// window.
5199TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5200 constexpr static int32_t displayWidth = 400;
5201 constexpr static int32_t displayHeight = 800;
5202
5203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5204
5205 const auto rotation = GetParam();
5206
5207 // Set up the display with the specified rotation.
5208 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5209 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5210 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5211 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5212 logicalDisplayWidth, logicalDisplayHeight);
5213 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5214
5215 // Create a window with its bounds determined in the logical display.
5216 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5217 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5218 sp<FakeWindowHandle> window =
5219 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5220 window->setFrame(frameInDisplay, displayTransform);
5221 addWindow(window);
5222
5223 // The following points in logical display space should be inside the window.
5224 static const std::array<vec2, 4> insidePoints{
5225 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5226 for (const auto pointInsideWindow : insidePoints) {
5227 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5228 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005229 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5230 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5231 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005232 window->consumeMotionDown();
5233
Prabir Pradhan678438e2023-04-13 19:32:51 +00005234 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5235 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5236 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005237 window->consumeMotionUp();
5238 }
5239
5240 // The following points in logical display space should be outside the window.
5241 static const std::array<vec2, 5> outsidePoints{
5242 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5243 for (const auto pointOutsideWindow : outsidePoints) {
5244 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5245 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005246 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5247 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5248 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005249
Prabir Pradhan678438e2023-04-13 19:32:51 +00005250 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5251 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5252 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005253 }
5254 window->assertNoEvents();
5255}
5256
5257// Run the precision tests for all rotations.
5258INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5259 InputDispatcherDisplayOrientationFixture,
5260 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5261 ui::ROTATION_270),
5262 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5263 return ftl::enum_string(testParamInfo.param);
5264 });
5265
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005266using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5267 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005268
5269class TransferTouchFixture : public InputDispatcherTest,
5270 public ::testing::WithParamInterface<TransferFunction> {};
5271
5272TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005273 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005274
5275 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005276 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005277 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5278 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005279 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005280 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005281 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5282 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005283 sp<FakeWindowHandle> wallpaper =
5284 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5285 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005286 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005287 mDispatcher->onWindowInfosChanged(
5288 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005289
5290 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005291 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5292 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005293
Svet Ganov5d3bc372020-01-26 23:11:07 -08005294 // Only the first window should get the down event
5295 firstWindow->consumeMotionDown();
5296 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005297 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005298
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005299 // Transfer touch to the second window
5300 TransferFunction f = GetParam();
5301 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5302 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005303 // The first window gets cancel and the second gets down
5304 firstWindow->consumeMotionCancel();
5305 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005306 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005307
5308 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005309 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5310 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005311 // The first window gets no events and the second gets up
5312 firstWindow->assertNoEvents();
5313 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005314 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005315}
5316
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005317/**
5318 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5319 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5320 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5321 * natural to the user.
5322 * In this test, we are sending a pointer to both spy window and first window. We then try to
5323 * transfer touch to the second window. The dispatcher should identify the first window as the
5324 * one that should lose the gesture, and therefore the action should be to move the gesture from
5325 * the first window to the second.
5326 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5327 * the other API, as well.
5328 */
5329TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5330 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5331
5332 // Create a couple of windows + a spy window
5333 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005334 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005335 spyWindow->setTrustedOverlay(true);
5336 spyWindow->setSpy(true);
5337 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005338 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005339 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005340 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005341
5342 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005343 mDispatcher->onWindowInfosChanged(
5344 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005345
5346 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005347 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5348 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005349 // Only the first window and spy should get the down event
5350 spyWindow->consumeMotionDown();
5351 firstWindow->consumeMotionDown();
5352
5353 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5354 // if f === 'transferTouch'.
5355 TransferFunction f = GetParam();
5356 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5357 ASSERT_TRUE(success);
5358 // The first window gets cancel and the second gets down
5359 firstWindow->consumeMotionCancel();
5360 secondWindow->consumeMotionDown();
5361
5362 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005363 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5364 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005365 // The first window gets no events and the second+spy get up
5366 firstWindow->assertNoEvents();
5367 spyWindow->consumeMotionUp();
5368 secondWindow->consumeMotionUp();
5369}
5370
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005371TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005373
5374 PointF touchPoint = {10, 10};
5375
5376 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005377 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005378 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5379 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005380 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005381 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005382 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5383 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005384 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005385
5386 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005387 mDispatcher->onWindowInfosChanged(
5388 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005389
5390 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005391 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5392 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5393 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005394 // Only the first window should get the down event
5395 firstWindow->consumeMotionDown();
5396 secondWindow->assertNoEvents();
5397
5398 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005399 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5400 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005401 // Only the first window should get the pointer down event
5402 firstWindow->consumeMotionPointerDown(1);
5403 secondWindow->assertNoEvents();
5404
5405 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005406 TransferFunction f = GetParam();
5407 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5408 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005409 // The first window gets cancel and the second gets down and pointer down
5410 firstWindow->consumeMotionCancel();
5411 secondWindow->consumeMotionDown();
5412 secondWindow->consumeMotionPointerDown(1);
5413
5414 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005415 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5416 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005417 // The first window gets nothing and the second gets pointer up
5418 firstWindow->assertNoEvents();
5419 secondWindow->consumeMotionPointerUp(1);
5420
5421 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5423 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005424 // The first window gets nothing and the second gets up
5425 firstWindow->assertNoEvents();
5426 secondWindow->consumeMotionUp();
5427}
5428
Arthur Hungc539dbb2022-12-08 07:45:36 +00005429TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5430 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5431
5432 // Create a couple of windows
5433 sp<FakeWindowHandle> firstWindow =
5434 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5435 ADISPLAY_ID_DEFAULT);
5436 firstWindow->setDupTouchToWallpaper(true);
5437 sp<FakeWindowHandle> secondWindow =
5438 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5439 ADISPLAY_ID_DEFAULT);
5440 secondWindow->setDupTouchToWallpaper(true);
5441
5442 sp<FakeWindowHandle> wallpaper1 =
5443 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5444 wallpaper1->setIsWallpaper(true);
5445
5446 sp<FakeWindowHandle> wallpaper2 =
5447 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5448 wallpaper2->setIsWallpaper(true);
5449 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005450 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5451 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5452 {},
5453 0,
5454 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005455
5456 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005457 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5458 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005459
5460 // Only the first window should get the down event
5461 firstWindow->consumeMotionDown();
5462 secondWindow->assertNoEvents();
5463 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5464 wallpaper2->assertNoEvents();
5465
5466 // Transfer touch focus to the second window
5467 TransferFunction f = GetParam();
5468 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5469 ASSERT_TRUE(success);
5470
5471 // The first window gets cancel and the second gets down
5472 firstWindow->consumeMotionCancel();
5473 secondWindow->consumeMotionDown();
5474 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5475 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5476
5477 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005478 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5479 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005480 // The first window gets no events and the second gets up
5481 firstWindow->assertNoEvents();
5482 secondWindow->consumeMotionUp();
5483 wallpaper1->assertNoEvents();
5484 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5485}
5486
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005487// For the cases of single pointer touch and two pointers non-split touch, the api's
5488// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5489// for the case where there are multiple pointers split across several windows.
5490INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5491 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005492 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5493 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005494 return dispatcher->transferTouch(destChannelToken,
5495 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005496 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005497 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5498 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005499 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005500 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005501 }));
5502
Svet Ganov5d3bc372020-01-26 23:11:07 -08005503TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005504 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005505
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005506 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005507 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5508 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005509 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005510
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005511 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005512 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5513 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005514 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005515
5516 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005517 mDispatcher->onWindowInfosChanged(
5518 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005519
5520 PointF pointInFirst = {300, 200};
5521 PointF pointInSecond = {300, 600};
5522
5523 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005524 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5525 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5526 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005527 // Only the first window should get the down event
5528 firstWindow->consumeMotionDown();
5529 secondWindow->assertNoEvents();
5530
5531 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005532 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5533 ADISPLAY_ID_DEFAULT,
5534 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005535 // The first window gets a move and the second a down
5536 firstWindow->consumeMotionMove();
5537 secondWindow->consumeMotionDown();
5538
5539 // Transfer touch focus to the second window
5540 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5541 // The first window gets cancel and the new gets pointer down (it already saw down)
5542 firstWindow->consumeMotionCancel();
5543 secondWindow->consumeMotionPointerDown(1);
5544
5545 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005546 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5547 ADISPLAY_ID_DEFAULT,
5548 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005549 // The first window gets nothing and the second gets pointer up
5550 firstWindow->assertNoEvents();
5551 secondWindow->consumeMotionPointerUp(1);
5552
5553 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005554 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5555 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005556 // The first window gets nothing and the second gets up
5557 firstWindow->assertNoEvents();
5558 secondWindow->consumeMotionUp();
5559}
5560
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005561// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5562// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5563// touch is not supported, so the touch should continue on those windows and the transferred-to
5564// window should get nothing.
5565TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5566 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5567
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005568 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005569 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5570 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005571 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005572
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005573 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005574 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5575 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005576 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005577
5578 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005579 mDispatcher->onWindowInfosChanged(
5580 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005581
5582 PointF pointInFirst = {300, 200};
5583 PointF pointInSecond = {300, 600};
5584
5585 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005586 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5587 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5588 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005589 // Only the first window should get the down event
5590 firstWindow->consumeMotionDown();
5591 secondWindow->assertNoEvents();
5592
5593 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005594 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5595 ADISPLAY_ID_DEFAULT,
5596 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005597 // The first window gets a move and the second a down
5598 firstWindow->consumeMotionMove();
5599 secondWindow->consumeMotionDown();
5600
5601 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005602 const bool transferred =
5603 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005604 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5605 ASSERT_FALSE(transferred);
5606 firstWindow->assertNoEvents();
5607 secondWindow->assertNoEvents();
5608
5609 // The rest of the dispatch should proceed as normal
5610 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005611 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5612 ADISPLAY_ID_DEFAULT,
5613 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005614 // The first window gets MOVE and the second gets pointer up
5615 firstWindow->consumeMotionMove();
5616 secondWindow->consumeMotionUp();
5617
5618 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005619 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5620 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005621 // The first window gets nothing and the second gets up
5622 firstWindow->consumeMotionUp();
5623 secondWindow->assertNoEvents();
5624}
5625
Arthur Hungabbb9d82021-09-01 14:52:30 +00005626// This case will create two windows and one mirrored window on the default display and mirror
5627// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5628// the windows info of second display before default display.
5629TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5630 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5631 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005632 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005633 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005634 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005635 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005636 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005637
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005638 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005639 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005640
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005641 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005642 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005643
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005644 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005645 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005646
5647 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005648 mDispatcher->onWindowInfosChanged(
5649 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5650 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5651 *secondWindowInPrimary->getInfo()},
5652 {},
5653 0,
5654 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005655
5656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005657 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005658 {50, 50}))
5659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5660
5661 // Window should receive motion event.
5662 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5663
5664 // Transfer touch focus
5665 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5666 secondWindowInPrimary->getToken()));
5667 // The first window gets cancel.
5668 firstWindowInPrimary->consumeMotionCancel();
5669 secondWindowInPrimary->consumeMotionDown();
5670
5671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005672 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005673 ADISPLAY_ID_DEFAULT, {150, 50}))
5674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5675 firstWindowInPrimary->assertNoEvents();
5676 secondWindowInPrimary->consumeMotionMove();
5677
5678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005679 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005680 {150, 50}))
5681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5682 firstWindowInPrimary->assertNoEvents();
5683 secondWindowInPrimary->consumeMotionUp();
5684}
5685
5686// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5687// 'transferTouch' api.
5688TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5690 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005691 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005692 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005693 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005694 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005695 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005696
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005697 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005698 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005699
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005700 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005701 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005702
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005703 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005704 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005705
5706 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005707 mDispatcher->onWindowInfosChanged(
5708 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5709 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5710 *secondWindowInPrimary->getInfo()},
5711 {},
5712 0,
5713 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005714
5715 // Touch on second display.
5716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5718 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5720
5721 // Window should receive motion event.
5722 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5723
5724 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005725 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005726
5727 // The first window gets cancel.
5728 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
5729 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
5730
5731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005732 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005733 SECOND_DISPLAY_ID, {150, 50}))
5734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5735 firstWindowInPrimary->assertNoEvents();
5736 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
5737
5738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005739 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5741 firstWindowInPrimary->assertNoEvents();
5742 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
5743}
5744
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005745TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005747 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5748 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005749
Vishnu Nair47074b82020-08-14 11:54:47 -07005750 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005751 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005752 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005753
5754 window->consumeFocusEvent(true);
5755
Prabir Pradhan678438e2023-04-13 19:32:51 +00005756 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005757
5758 // Window should receive key down event.
5759 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005760
5761 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005762 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005763 mFakePolicy->assertUserActivityPoked();
5764}
5765
5766TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5768 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5769 "Fake Window", ADISPLAY_ID_DEFAULT);
5770
5771 window->setDisableUserActivity(true);
5772 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005773 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005774 setFocusedWindow(window);
5775
5776 window->consumeFocusEvent(true);
5777
5778 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5779
5780 // Window should receive key down event.
5781 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5782
5783 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005784 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005785 mFakePolicy->assertUserActivityNotPoked();
5786}
5787
5788TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5790 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5791 "Fake Window", ADISPLAY_ID_DEFAULT);
5792
5793 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005794 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005795 setFocusedWindow(window);
5796
5797 window->consumeFocusEvent(true);
5798
5799 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5800 mDispatcher->waitForIdle();
5801
5802 // System key is not passed down
5803 window->assertNoEvents();
5804
5805 // Should have poked user activity
5806 mFakePolicy->assertUserActivityPoked();
5807}
5808
5809TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5812 "Fake Window", ADISPLAY_ID_DEFAULT);
5813
5814 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005816 setFocusedWindow(window);
5817
5818 window->consumeFocusEvent(true);
5819
5820 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5821 mDispatcher->waitForIdle();
5822
5823 // System key is not passed down
5824 window->assertNoEvents();
5825
5826 // Should have poked user activity
5827 mFakePolicy->assertUserActivityPoked();
5828}
5829
5830TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5832 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5833 "Fake Window", ADISPLAY_ID_DEFAULT);
5834
5835 window->setDisableUserActivity(true);
5836 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005837 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005838 setFocusedWindow(window);
5839
5840 window->consumeFocusEvent(true);
5841
5842 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5843 mDispatcher->waitForIdle();
5844
5845 // System key is not passed down
5846 window->assertNoEvents();
5847
5848 // Should have poked user activity
5849 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005850}
5851
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005852TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5854 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5855 "Fake Window", ADISPLAY_ID_DEFAULT);
5856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005857 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005858
5859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005860 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005861 ADISPLAY_ID_DEFAULT, {100, 100}))
5862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5863
5864 window->consumeMotionEvent(
5865 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5866
5867 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005868 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005869 mFakePolicy->assertUserActivityPoked();
5870}
5871
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005872TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5875 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005878
Prabir Pradhan678438e2023-04-13 19:32:51 +00005879 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005880 mDispatcher->waitForIdle();
5881
5882 window->assertNoEvents();
5883}
5884
5885// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5886TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005888 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5889 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005890
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005891 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005892
5893 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005894 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005895 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005896 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5897 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005898
5899 // Window should receive only the motion event
5900 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5901 window->assertNoEvents(); // Key event or focus event will not be received
5902}
5903
arthurhungea3f4fc2020-12-21 23:18:53 +08005904TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5906
arthurhungea3f4fc2020-12-21 23:18:53 +08005907 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005908 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5909 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005910 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005911
arthurhungea3f4fc2020-12-21 23:18:53 +08005912 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005913 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5914 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005915 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005916
5917 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005918 mDispatcher->onWindowInfosChanged(
5919 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005920
5921 PointF pointInFirst = {300, 200};
5922 PointF pointInSecond = {300, 600};
5923
5924 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005925 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5926 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5927 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005928 // Only the first window should get the down event
5929 firstWindow->consumeMotionDown();
5930 secondWindow->assertNoEvents();
5931
5932 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005933 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5934 ADISPLAY_ID_DEFAULT,
5935 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005936 // The first window gets a move and the second a down
5937 firstWindow->consumeMotionMove();
5938 secondWindow->consumeMotionDown();
5939
5940 // Send pointer cancel to the second window
5941 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005942 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005943 {pointInFirst, pointInSecond});
5944 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005945 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005946 // The first window gets move and the second gets cancel.
5947 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5948 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5949
5950 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005951 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5952 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005953 // The first window gets up and the second gets nothing.
5954 firstWindow->consumeMotionUp();
5955 secondWindow->assertNoEvents();
5956}
5957
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005958TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5960
5961 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005962 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005963 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005964 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5965 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5966 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5967
Harry Cutts33476232023-01-30 19:57:29 +00005968 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005969 window->assertNoEvents();
5970 mDispatcher->waitForIdle();
5971}
5972
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005973using InputDispatcherMonitorTest = InputDispatcherTest;
5974
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005975/**
5976 * Two entities that receive touch: A window, and a global monitor.
5977 * The touch goes to the window, and then the window disappears.
5978 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5979 * for the monitor, as well.
5980 * 1. foregroundWindow
5981 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5982 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005983TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5985 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005986 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005987
Prabir Pradhanfb549072023-10-05 19:17:36 +00005988 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005990 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005992 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005993 {100, 200}))
5994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5995
5996 // Both the foreground window and the global monitor should receive the touch down
5997 window->consumeMotionDown();
5998 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5999
6000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006001 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006002 ADISPLAY_ID_DEFAULT, {110, 200}))
6003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6004
6005 window->consumeMotionMove();
6006 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6007
6008 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006009 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006010 window->consumeMotionCancel();
6011 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6012
6013 // If more events come in, there will be no more foreground window to send them to. This will
6014 // cause a cancel for the monitor, as well.
6015 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006016 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006017 ADISPLAY_ID_DEFAULT, {120, 200}))
6018 << "Injection should fail because the window was removed";
6019 window->assertNoEvents();
6020 // Global monitor now gets the cancel
6021 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6022}
6023
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006024TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006026 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6027 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006028 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006029
Prabir Pradhanfb549072023-10-05 19:17:36 +00006030 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006031
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006033 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006035 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006036 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006037}
6038
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006039TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006040 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006041
Chris Yea209fde2020-07-22 13:54:51 -07006042 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006043 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6044 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006045 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006046
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006048 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006049 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006050 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006051 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006052
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006053 // Pilfer pointers from the monitor.
6054 // This should not do anything and the window should continue to receive events.
6055 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006056
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006058 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006059 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006060 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006061
6062 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6063 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006064}
6065
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006066TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006067 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006068 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6069 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006070 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006071 window->setWindowOffset(20, 40);
6072 window->setWindowTransform(0, 1, -1, 0);
6073
Prabir Pradhanfb549072023-10-05 19:17:36 +00006074 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006075
6076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006077 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6079 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006080 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6081 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006082 // Even though window has transform, gesture monitor must not.
6083 ASSERT_EQ(ui::Transform(), event->getTransform());
6084}
6085
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006086TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006088 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006089
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006090 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006091 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006092 << "Injection should fail if there is a monitor, but no touchable window";
6093 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006094}
6095
chaviw81e2bb92019-12-18 15:03:51 -08006096TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006097 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006098 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6099 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006100
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006101 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006102
6103 NotifyMotionArgs motionArgs =
6104 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6105 ADISPLAY_ID_DEFAULT);
6106
Prabir Pradhan678438e2023-04-13 19:32:51 +00006107 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006108 // Window should receive motion down event.
6109 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6110
6111 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006112 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006113 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6114 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6115 motionArgs.pointerCoords[0].getX() - 10);
6116
Prabir Pradhan678438e2023-04-13 19:32:51 +00006117 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006118 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006119}
6120
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006121/**
6122 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6123 * the device default right away. In the test scenario, we check both the default value,
6124 * and the action of enabling / disabling.
6125 */
6126TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006128 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6129 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006130 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006131
6132 // Set focused application.
6133 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006134 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006135
6136 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006137 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006138 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006139 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006140
6141 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006142 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006143 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006144 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006145
6146 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006147 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006148 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006149 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006150 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006151 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006152 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006153 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006154
6155 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006156 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006157 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006158 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006159
6160 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006161 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006162 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006163 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006164 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006166 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006167 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006168
6169 window->assertNoEvents();
6170}
6171
Gang Wange9087892020-01-07 12:17:14 -05006172TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006174 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6175 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006176
6177 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006178 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006179
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006180 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006181 setFocusedWindow(window);
6182
Harry Cutts33476232023-01-30 19:57:29 +00006183 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006184
Prabir Pradhan678438e2023-04-13 19:32:51 +00006185 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6186 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006187
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006188 std::unique_ptr<KeyEvent> event = window->consumeKey();
6189 ASSERT_NE(event, nullptr);
6190 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006191 ASSERT_NE(verified, nullptr);
6192 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6193
6194 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6195 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6196 ASSERT_EQ(keyArgs.source, verified->source);
6197 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6198
6199 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6200
6201 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006202 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006203 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006204 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6205 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6206 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6207 ASSERT_EQ(0, verifiedKey.repeatCount);
6208}
6209
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006210TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006212 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6213 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006214
6215 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6216
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006217 ui::Transform transform;
6218 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6219
6220 gui::DisplayInfo displayInfo;
6221 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6222 displayInfo.transform = transform;
6223
Patrick Williamsd828f302023-04-28 17:52:08 -05006224 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006225
Prabir Pradhan678438e2023-04-13 19:32:51 +00006226 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006227 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6228 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006229 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006230
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006231 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6232 ASSERT_NE(nullptr, event);
6233 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006234 ASSERT_NE(verified, nullptr);
6235 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6236
6237 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6238 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6239 EXPECT_EQ(motionArgs.source, verified->source);
6240 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6241
6242 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6243
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006244 const vec2 rawXY =
6245 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6246 motionArgs.pointerCoords[0].getXYValue());
6247 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6248 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006249 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006250 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006251 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006252 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6253 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6254}
6255
chaviw09c8d2d2020-08-24 15:48:26 -07006256/**
6257 * Ensure that separate calls to sign the same data are generating the same key.
6258 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6259 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6260 * tests.
6261 */
6262TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6263 KeyEvent event = getTestKeyEvent();
6264 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6265
6266 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6267 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6268 ASSERT_EQ(hmac1, hmac2);
6269}
6270
6271/**
6272 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6273 */
6274TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6275 KeyEvent event = getTestKeyEvent();
6276 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6277 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6278
6279 verifiedEvent.deviceId += 1;
6280 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6281
6282 verifiedEvent.source += 1;
6283 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6284
6285 verifiedEvent.eventTimeNanos += 1;
6286 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6287
6288 verifiedEvent.displayId += 1;
6289 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6290
6291 verifiedEvent.action += 1;
6292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6293
6294 verifiedEvent.downTimeNanos += 1;
6295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6296
6297 verifiedEvent.flags += 1;
6298 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6299
6300 verifiedEvent.keyCode += 1;
6301 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6302
6303 verifiedEvent.scanCode += 1;
6304 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6305
6306 verifiedEvent.metaState += 1;
6307 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6308
6309 verifiedEvent.repeatCount += 1;
6310 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6311}
6312
Vishnu Nair958da932020-08-21 17:12:37 -07006313TEST_F(InputDispatcherTest, SetFocusedWindow) {
6314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6315 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006316 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006317 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006318 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006319 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6320
6321 // Top window is also focusable but is not granted focus.
6322 windowTop->setFocusable(true);
6323 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006324 mDispatcher->onWindowInfosChanged(
6325 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006326 setFocusedWindow(windowSecond);
6327
6328 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006330 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006331
6332 // Focused window should receive event.
6333 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6334 windowTop->assertNoEvents();
6335}
6336
6337TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6339 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006340 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006341 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6342
6343 window->setFocusable(true);
6344 // Release channel for window is no longer valid.
6345 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006346 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006347 setFocusedWindow(window);
6348
6349 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006350 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006351
6352 // window channel is invalid, so it should not receive any input event.
6353 window->assertNoEvents();
6354}
6355
6356TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
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);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006360 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006361 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6362
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006364 setFocusedWindow(window);
6365
6366 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006367 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006368
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006369 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006370 window->assertNoEvents();
6371}
6372
6373TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6375 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006376 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006377 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006378 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006379 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6380
6381 windowTop->setFocusable(true);
6382 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006383 mDispatcher->onWindowInfosChanged(
6384 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006385 setFocusedWindow(windowTop);
6386 windowTop->consumeFocusEvent(true);
6387
Chavi Weingarten847e8512023-03-29 00:26:09 +00006388 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006389 mDispatcher->onWindowInfosChanged(
6390 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006391 windowSecond->consumeFocusEvent(true);
6392 windowTop->consumeFocusEvent(false);
6393
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006395 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006396
6397 // Focused window should receive event.
6398 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6399}
6400
Chavi Weingarten847e8512023-03-29 00:26:09 +00006401TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006402 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6403 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006404 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006405 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006406 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006407 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6408
6409 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006410 windowSecond->setFocusable(false);
6411 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006412 mDispatcher->onWindowInfosChanged(
6413 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006414 setFocusedWindow(windowTop);
6415 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006416
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006418 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006419
6420 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006421 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006422 windowSecond->assertNoEvents();
6423}
6424
6425TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6427 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006428 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006429 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006430 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6431 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006432 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6433
6434 window->setFocusable(true);
6435 previousFocusedWindow->setFocusable(true);
6436 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006437 mDispatcher->onWindowInfosChanged(
6438 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006439 setFocusedWindow(previousFocusedWindow);
6440 previousFocusedWindow->consumeFocusEvent(true);
6441
6442 // Requesting focus on invisible window takes focus from currently focused window.
6443 setFocusedWindow(window);
6444 previousFocusedWindow->consumeFocusEvent(false);
6445
6446 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006448 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6449 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006450
6451 // Window does not get focus event or key down.
6452 window->assertNoEvents();
6453
6454 // Window becomes visible.
6455 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006456 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006457
6458 // Window receives focus event.
6459 window->consumeFocusEvent(true);
6460 // Focused window receives key down.
6461 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6462}
6463
Vishnu Nair599f1412021-06-21 10:39:58 -07006464TEST_F(InputDispatcherTest, DisplayRemoved) {
6465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6466 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006467 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006468 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6469
6470 // window is granted focus.
6471 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006472 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006473 setFocusedWindow(window);
6474 window->consumeFocusEvent(true);
6475
6476 // When a display is removed window loses focus.
6477 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6478 window->consumeFocusEvent(false);
6479}
6480
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006481/**
6482 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6483 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6484 * of the 'slipperyEnterWindow'.
6485 *
6486 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6487 * a way so that the touched location is no longer covered by the top window.
6488 *
6489 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6490 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6491 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6492 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6493 * with ACTION_DOWN).
6494 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6495 * window moved itself away from the touched location and had Flag::SLIPPERY.
6496 *
6497 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6498 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6499 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6500 *
6501 * In this test, we ensure that the event received by the bottom window has
6502 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6503 */
6504TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006505 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006506 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006507
6508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6509 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6510
6511 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006512 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006513 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006514 // Make sure this one overlaps the bottom window
6515 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6516 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6517 // one. Windows with the same owner are not considered to be occluding each other.
6518 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6519
6520 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006521 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006522 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6523
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006524 mDispatcher->onWindowInfosChanged(
6525 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006526
6527 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6529 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6530 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006531 slipperyExitWindow->consumeMotionDown();
6532 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006533 mDispatcher->onWindowInfosChanged(
6534 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006535
Prabir Pradhan678438e2023-04-13 19:32:51 +00006536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6537 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6538 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006539
6540 slipperyExitWindow->consumeMotionCancel();
6541
6542 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6543 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6544}
6545
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006546/**
6547 * Two windows, one on the left and another on the right. The left window is slippery. The right
6548 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6549 * touch moves from the left window into the right window, the gesture should continue to go to the
6550 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6551 * reproduces a crash.
6552 */
6553TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6555
6556 sp<FakeWindowHandle> leftSlipperyWindow =
6557 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6558 leftSlipperyWindow->setSlippery(true);
6559 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6560
6561 sp<FakeWindowHandle> rightDropTouchesWindow =
6562 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6563 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6564 rightDropTouchesWindow->setDropInput(true);
6565
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006566 mDispatcher->onWindowInfosChanged(
6567 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006568
6569 // Start touch in the left window
6570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6571 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6572 .build());
6573 leftSlipperyWindow->consumeMotionDown();
6574
6575 // And move it into the right window
6576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6577 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6578 .build());
6579
6580 // Since the right window isn't eligible to receive input, touch does not slip.
6581 // The left window continues to receive the gesture.
6582 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6583 rightDropTouchesWindow->assertNoEvents();
6584}
6585
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006586/**
6587 * A single window is on screen first. Touch is injected into that window. Next, a second window
6588 * appears. Since the first window is slippery, touch will move from the first window to the second.
6589 */
6590TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6591 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6592 sp<FakeWindowHandle> originalWindow =
6593 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6594 originalWindow->setFrame(Rect(0, 0, 200, 200));
6595 originalWindow->setSlippery(true);
6596
6597 sp<FakeWindowHandle> appearingWindow =
6598 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6599 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6600
6601 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6602
6603 // Touch down on the original window
6604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6605 injectMotionEvent(*mDispatcher,
6606 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6607 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6608 .build()));
6609 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6610
6611 // Now, a new window appears. This could be, for example, a notification shade that appears
6612 // after user starts to drag down on the launcher window.
6613 mDispatcher->onWindowInfosChanged(
6614 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6616 injectMotionEvent(*mDispatcher,
6617 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6618 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6619 .build()));
6620 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6621 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6623 injectMotionEvent(*mDispatcher,
6624 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6625 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6626 .build()));
6627 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6628
6629 originalWindow->assertNoEvents();
6630 appearingWindow->assertNoEvents();
6631}
6632
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006633TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006634 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006635 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6636
6637 sp<FakeWindowHandle> leftWindow =
6638 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6639 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006640 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006641
6642 sp<FakeWindowHandle> rightSpy =
6643 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6644 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006645 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006646 rightSpy->setSpy(true);
6647 rightSpy->setTrustedOverlay(true);
6648
6649 sp<FakeWindowHandle> rightWindow =
6650 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6651 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006652 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006653
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006654 mDispatcher->onWindowInfosChanged(
6655 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006656
6657 // Touch in the left window
6658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6659 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6660 .build());
6661 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6662 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006663 ASSERT_NO_FATAL_FAILURE(
6664 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006665
6666 // Touch another finger over the right windows
6667 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6668 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6669 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6670 .build());
6671 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6672 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6673 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6674 mDispatcher->waitForIdle();
6675 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006676 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6677 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006678
6679 // Release finger over left window. The UP actions are not treated as device interaction.
6680 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6681 // is part of the UP action, we do not treat this as device interaction.
6682 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6683 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6684 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6685 .build());
6686 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6687 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6688 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6689 mDispatcher->waitForIdle();
6690 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6691
6692 // Move remaining finger
6693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6694 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6695 .build());
6696 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6697 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6698 mDispatcher->waitForIdle();
6699 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006700 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006701
6702 // Release all fingers
6703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6704 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6705 .build());
6706 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6707 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6708 mDispatcher->waitForIdle();
6709 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6710}
6711
6712TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6714
6715 sp<FakeWindowHandle> window =
6716 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6717 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006718 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006719
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006720 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006721 setFocusedWindow(window);
6722 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6723
6724 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6725 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6726 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006727 ASSERT_NO_FATAL_FAILURE(
6728 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006729
6730 // The UP actions are not treated as device interaction.
6731 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6732 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6733 mDispatcher->waitForIdle();
6734 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6735}
6736
Prabir Pradhan5893d362023-11-17 04:30:40 +00006737TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6739
6740 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6741 ADISPLAY_ID_DEFAULT);
6742 left->setFrame(Rect(0, 0, 100, 100));
6743 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6744 "Right Window", ADISPLAY_ID_DEFAULT);
6745 right->setFrame(Rect(100, 0, 200, 100));
6746 sp<FakeWindowHandle> spy =
6747 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6748 spy->setFrame(Rect(0, 0, 200, 100));
6749 spy->setTrustedOverlay(true);
6750 spy->setSpy(true);
6751
6752 mDispatcher->onWindowInfosChanged(
6753 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6754
6755 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6756 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6757 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6758 mDispatcher->notifyMotion(notifyArgs);
6759
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006760 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00006761 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6762 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006763 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00006764 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6765 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006766 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00006767 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6768
6769 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6770 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6771 {PointF{150, 50}});
6772 mDispatcher->notifyMotion(notifyArgs);
6773
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006774 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00006775 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6776 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006777 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00006778 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6779 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006780 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00006781 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6782
6783 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6784}
6785
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006786class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6787protected:
6788 std::shared_ptr<FakeApplicationHandle> mApp;
6789 sp<FakeWindowHandle> mWindow;
6790
6791 virtual void SetUp() override {
6792 InputDispatcherTest::SetUp();
6793
6794 mApp = std::make_shared<FakeApplicationHandle>();
6795
6796 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6797 mWindow->setFrame(Rect(0, 0, 100, 100));
6798
6799 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6800 setFocusedWindow(mWindow);
6801 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6802 }
6803
6804 void setFallback(int32_t keycode) {
6805 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6806 return KeyEventBuilder(event).keyCode(keycode).build();
6807 });
6808 }
6809
6810 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006811 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
6812 ASSERT_NE(nullptr, event);
6813 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006814 }
6815};
6816
6817TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6818 mDispatcher->notifyKey(
6819 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6820 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6821 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6822}
6823
6824TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6825 mDispatcher->notifyKey(
6826 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6827 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6828 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6829}
6830
6831TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6832 mDispatcher->notifyKey(
6833 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6834
6835 // Do not handle this key event.
6836 consumeKey(/*handled=*/false,
6837 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6838 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6839
6840 // Since the policy did not request any fallback to be generated, ensure there are no events.
6841 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6842}
6843
6844TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6845 setFallback(AKEYCODE_B);
6846 mDispatcher->notifyKey(
6847 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6848
6849 // Do not handle this key event.
6850 consumeKey(/*handled=*/false,
6851 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6852
6853 // Since the key was not handled, ensure the fallback event was dispatched instead.
6854 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6855 consumeKey(/*handled=*/true,
6856 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6857 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6858
6859 // Release the original key, and ensure the fallback key is also released.
6860 mDispatcher->notifyKey(
6861 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6862 consumeKey(/*handled=*/false,
6863 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6864 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6865 consumeKey(/*handled=*/true,
6866 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6867 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6868
6869 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6870 mWindow->assertNoEvents();
6871}
6872
6873TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6874 setFallback(AKEYCODE_B);
6875 mDispatcher->notifyKey(
6876 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6877
6878 // Do not handle this key event, but handle the fallback.
6879 consumeKey(/*handled=*/false,
6880 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6881 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6882 consumeKey(/*handled=*/true,
6883 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6884 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6885
6886 // Release the original key, and ensure the fallback key is also released.
6887 mDispatcher->notifyKey(
6888 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6889 // But this time, the app handles the original key.
6890 consumeKey(/*handled=*/true,
6891 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6892 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6893 // Ensure the fallback key is canceled.
6894 consumeKey(/*handled=*/true,
6895 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6896 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6897
6898 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6899 mWindow->assertNoEvents();
6900}
6901
6902TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6903 setFallback(AKEYCODE_B);
6904 mDispatcher->notifyKey(
6905 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6906
6907 // Do not handle this key event.
6908 consumeKey(/*handled=*/false,
6909 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6910 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6911 // App does not handle the fallback either, so ensure another fallback is not generated.
6912 setFallback(AKEYCODE_C);
6913 consumeKey(/*handled=*/false,
6914 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6915 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6916
6917 // Release the original key, and ensure the fallback key is also released.
6918 setFallback(AKEYCODE_B);
6919 mDispatcher->notifyKey(
6920 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6921 consumeKey(/*handled=*/false,
6922 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6923 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6924 consumeKey(/*handled=*/false,
6925 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6926 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6927
6928 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6929 mWindow->assertNoEvents();
6930}
6931
6932TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6933 setFallback(AKEYCODE_B);
6934 mDispatcher->notifyKey(
6935 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6936
6937 // Do not handle this key event, so fallback is generated.
6938 consumeKey(/*handled=*/false,
6939 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6940 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6941 consumeKey(/*handled=*/true,
6942 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6943 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6944
6945 // Release the original key, but assume the policy is misbehaving and it
6946 // generates an inconsistent fallback to the one from the DOWN event.
6947 setFallback(AKEYCODE_C);
6948 mDispatcher->notifyKey(
6949 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6950 consumeKey(/*handled=*/false,
6951 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6952 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6953 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6954 consumeKey(/*handled=*/true,
6955 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6956 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6957
6958 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6959 mWindow->assertNoEvents();
6960}
6961
6962TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6963 setFallback(AKEYCODE_B);
6964 mDispatcher->notifyKey(
6965 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6966
6967 // Do not handle this key event, so fallback is generated.
6968 consumeKey(/*handled=*/false,
6969 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6970 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6971 consumeKey(/*handled=*/true,
6972 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6973 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6974
6975 // The original key is canceled.
6976 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6977 .keyCode(AKEYCODE_A)
6978 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6979 .build());
6980 consumeKey(/*handled=*/false,
6981 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6982 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6983 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6984 // Ensure the fallback key is also canceled due to the original key being canceled.
6985 consumeKey(/*handled=*/true,
6986 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6987 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6988
6989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6990 mWindow->assertNoEvents();
6991}
6992
Garfield Tan1c7bc862020-01-28 13:24:04 -08006993class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
6994protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08006995 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
6996 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006997
Chris Yea209fde2020-07-22 13:54:51 -07006998 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08006999 sp<FakeWindowHandle> mWindow;
7000
7001 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00007002 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00007003 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00007004 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09007005 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007006 ASSERT_EQ(OK, mDispatcher->start());
7007
7008 setUpWindow();
7009 }
7010
7011 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007012 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007013 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007014
Vishnu Nair47074b82020-08-14 11:54:47 -07007015 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007016 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007017 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007018 mWindow->consumeFocusEvent(true);
7019 }
7020
Chris Ye2ad95392020-09-01 13:44:44 -07007021 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007022 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007023 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007024 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007025 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007026
7027 // Window should receive key down event.
7028 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7029 }
7030
7031 void expectKeyRepeatOnce(int32_t repeatCount) {
7032 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007033 mWindow->consumeKeyEvent(
7034 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007035 }
7036
Chris Ye2ad95392020-09-01 13:44:44 -07007037 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007038 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007039 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007040 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007041 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007042
7043 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007044 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007045 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007046 }
7047};
7048
7049TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007050 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007051 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7052 expectKeyRepeatOnce(repeatCount);
7053 }
7054}
7055
7056TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007057 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007058 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7059 expectKeyRepeatOnce(repeatCount);
7060 }
Harry Cutts33476232023-01-30 19:57:29 +00007061 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007062 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007063 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7064 expectKeyRepeatOnce(repeatCount);
7065 }
7066}
7067
7068TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007069 sendAndConsumeKeyDown(/*deviceId=*/1);
7070 expectKeyRepeatOnce(/*repeatCount=*/1);
7071 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007072 mWindow->assertNoEvents();
7073}
7074
7075TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007076 sendAndConsumeKeyDown(/*deviceId=*/1);
7077 expectKeyRepeatOnce(/*repeatCount=*/1);
7078 sendAndConsumeKeyDown(/*deviceId=*/2);
7079 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007080 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007081 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007082 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007083 expectKeyRepeatOnce(/*repeatCount=*/2);
7084 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007085 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007086 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007087 mWindow->assertNoEvents();
7088}
7089
7090TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007091 sendAndConsumeKeyDown(/*deviceId=*/1);
7092 expectKeyRepeatOnce(/*repeatCount=*/1);
7093 sendAndConsumeKeyDown(/*deviceId=*/2);
7094 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007095 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007096 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007097 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007098 mWindow->assertNoEvents();
7099}
7100
liushenxiang42232912021-05-21 20:24:09 +08007101TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7102 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007103 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007104 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007105 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7106 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7107 mWindow->assertNoEvents();
7108}
7109
Garfield Tan1c7bc862020-01-28 13:24:04 -08007110TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007111 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007112 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007113 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007114 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7115 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007116 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007117 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007118 }
7119}
7120
7121TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007122 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007123 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007124
7125 std::unordered_set<int32_t> idSet;
7126 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007127 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7128 ASSERT_NE(nullptr, repeatEvent);
7129 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007130 EXPECT_EQ(idSet.end(), idSet.find(id));
7131 idSet.insert(id);
7132 }
7133}
7134
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007135/* Test InputDispatcher for MultiDisplay */
7136class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7137public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007138 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007139 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007140
Chris Yea209fde2020-07-22 13:54:51 -07007141 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007142 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007143 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007144
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007145 // Set focus window for primary display, but focused display would be second one.
7146 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007147 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007148 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7149
Vishnu Nair958da932020-08-21 17:12:37 -07007150 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007151 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007152
Chris Yea209fde2020-07-22 13:54:51 -07007153 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007154 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007155 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007156 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007157 // Set focus display to second one.
7158 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7159 // Set focus window for second display.
7160 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007161 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007162 mDispatcher->onWindowInfosChanged(
7163 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007164 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007165 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007166 }
7167
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007168 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007169 InputDispatcherTest::TearDown();
7170
Chris Yea209fde2020-07-22 13:54:51 -07007171 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007172 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007173 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007174 windowInSecondary.clear();
7175 }
7176
7177protected:
Chris Yea209fde2020-07-22 13:54:51 -07007178 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007179 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007180 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007181 sp<FakeWindowHandle> windowInSecondary;
7182};
7183
7184TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7185 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007187 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007189 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007190 windowInSecondary->assertNoEvents();
7191
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007192 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007194 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007196 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007197 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007198}
7199
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007200TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007201 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007203 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007204 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007205 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007206 windowInSecondary->assertNoEvents();
7207
7208 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007210 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007211 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007212 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007213
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007214 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007215 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007216
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007217 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007218 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007219
7220 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007221 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007222 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007223 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007224 windowInSecondary->assertNoEvents();
7225}
7226
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007227// Test per-display input monitors for motion event.
7228TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007229 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007230 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007231 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007232 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007233
7234 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007238 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007239 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007240 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007241 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007242
7243 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007245 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007247 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007248 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007249 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007250 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007251
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007252 // Lift up the touch from the second display
7253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007254 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7256 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7257 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7258
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007259 // Test inject a non-pointer motion event.
7260 // If specific a display, it will dispatch to the focused window of particular display,
7261 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007264 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007265 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007266 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007267 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007268 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007269}
7270
7271// Test per-display input monitors for key event.
7272TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007273 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007274 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007275 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007276 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007277 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007278
7279 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007281 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007282 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007283 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007284 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007285 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007286}
7287
Vishnu Nair958da932020-08-21 17:12:37 -07007288TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7289 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007290 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007291 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007292 mDispatcher->onWindowInfosChanged(
7293 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7294 *windowInSecondary->getInfo()},
7295 {},
7296 0,
7297 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007298 setFocusedWindow(secondWindowInPrimary);
7299 windowInPrimary->consumeFocusEvent(false);
7300 secondWindowInPrimary->consumeFocusEvent(true);
7301
7302 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7304 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007305 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007306 windowInPrimary->assertNoEvents();
7307 windowInSecondary->assertNoEvents();
7308 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7309}
7310
Arthur Hungdfd528e2021-12-08 13:23:04 +00007311TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7312 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007313 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007314 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007315 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007316
7317 // Test touch down on primary display.
7318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007319 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007320 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7321 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7322 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7323
7324 // Test touch down on second display.
7325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007326 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007327 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7328 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7329 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7330
7331 // Trigger cancel touch.
7332 mDispatcher->cancelCurrentTouch();
7333 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7334 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7335 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7336 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7337
7338 // Test inject a move motion event, no window/monitor should receive the event.
7339 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007340 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007341 ADISPLAY_ID_DEFAULT, {110, 200}))
7342 << "Inject motion event should return InputEventInjectionResult::FAILED";
7343 windowInPrimary->assertNoEvents();
7344 monitorInPrimary.assertNoEvents();
7345
7346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007347 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007348 SECOND_DISPLAY_ID, {110, 200}))
7349 << "Inject motion event should return InputEventInjectionResult::FAILED";
7350 windowInSecondary->assertNoEvents();
7351 monitorInSecondary.assertNoEvents();
7352}
7353
Jackal Guof9696682018-10-05 12:23:23 +08007354class InputFilterTest : public InputDispatcherTest {
7355protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007356 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7357 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007358 NotifyMotionArgs motionArgs;
7359
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007360 motionArgs =
7361 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007362 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007363 motionArgs =
7364 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007365 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007366 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007367 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007368 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007369 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007370 } else {
7371 mFakePolicy->assertFilterInputEventWasNotCalled();
7372 }
7373 }
7374
7375 void testNotifyKey(bool expectToBeFiltered) {
7376 NotifyKeyArgs keyArgs;
7377
7378 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007379 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007380 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007381 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007382 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007383
7384 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007385 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007386 } else {
7387 mFakePolicy->assertFilterInputEventWasNotCalled();
7388 }
7389 }
7390};
7391
7392// Test InputFilter for MotionEvent
7393TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7394 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007395 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7396 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007397
7398 // Enable InputFilter
7399 mDispatcher->setInputFilterEnabled(true);
7400 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007401 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7402 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007403
7404 // Disable InputFilter
7405 mDispatcher->setInputFilterEnabled(false);
7406 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007407 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7408 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007409}
7410
7411// Test InputFilter for KeyEvent
7412TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7413 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007414 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007415
7416 // Enable InputFilter
7417 mDispatcher->setInputFilterEnabled(true);
7418 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007419 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007420
7421 // Disable InputFilter
7422 mDispatcher->setInputFilterEnabled(false);
7423 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007424 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007425}
7426
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007427// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7428// logical display coordinate space.
7429TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7430 ui::Transform firstDisplayTransform;
7431 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7432 ui::Transform secondDisplayTransform;
7433 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7434
7435 std::vector<gui::DisplayInfo> displayInfos(2);
7436 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7437 displayInfos[0].transform = firstDisplayTransform;
7438 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7439 displayInfos[1].transform = secondDisplayTransform;
7440
Patrick Williamsd828f302023-04-28 17:52:08 -05007441 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007442
7443 // Enable InputFilter
7444 mDispatcher->setInputFilterEnabled(true);
7445
7446 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007447 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7448 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007449}
7450
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007451class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7452protected:
7453 virtual void SetUp() override {
7454 InputDispatcherTest::SetUp();
7455
7456 /**
7457 * We don't need to enable input filter to test the injected event policy, but we enabled it
7458 * here to make the tests more realistic, since this policy only matters when inputfilter is
7459 * on.
7460 */
7461 mDispatcher->setInputFilterEnabled(true);
7462
7463 std::shared_ptr<InputApplicationHandle> application =
7464 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007465 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7466 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007467
7468 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7469 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007470 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007471 setFocusedWindow(mWindow);
7472 mWindow->consumeFocusEvent(true);
7473 }
7474
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007475 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7476 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007477 KeyEvent event;
7478
7479 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7480 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7481 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007482 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007483 const int32_t additionalPolicyFlags =
7484 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007486 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007487 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007488 policyFlags | additionalPolicyFlags));
7489
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007490 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007491 }
7492
7493 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7494 int32_t flags) {
7495 MotionEvent event;
7496 PointerProperties pointerProperties[1];
7497 PointerCoords pointerCoords[1];
7498 pointerProperties[0].clear();
7499 pointerProperties[0].id = 0;
7500 pointerCoords[0].clear();
7501 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7502 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7503
7504 ui::Transform identityTransform;
7505 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7506 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7507 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7508 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7509 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007510 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007511 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007512 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007513
7514 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007516 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007517 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007518 policyFlags | additionalPolicyFlags));
7519
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007520 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007521 }
7522
7523private:
7524 sp<FakeWindowHandle> mWindow;
7525};
7526
7527TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007528 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7529 // filter. Without it, the event will no different from a regularly injected event, and the
7530 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007531 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7532 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007533}
7534
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007535TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007536 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007537 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007538 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7539}
7540
7541TEST_F(InputFilterInjectionPolicyTest,
7542 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7543 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007544 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007545 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007546}
7547
7548TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007549 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7550 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007551}
7552
chaviwfd6d3512019-03-25 13:23:49 -07007553class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007554 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007555 InputDispatcherTest::SetUp();
7556
Chris Yea209fde2020-07-22 13:54:51 -07007557 std::shared_ptr<FakeApplicationHandle> application =
7558 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007559 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007560 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007561 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007562
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007563 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007564 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007565 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007566
7567 // Set focused application.
7568 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007569 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007570
7571 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007572 mDispatcher->onWindowInfosChanged(
7573 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007574 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007575 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007576 }
7577
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007578 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007579 InputDispatcherTest::TearDown();
7580
7581 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007582 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007583 }
7584
7585protected:
7586 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007587 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007588 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007589};
7590
7591// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7592// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7593// the onPointerDownOutsideFocus callback.
7594TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007596 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007597 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007599 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007600
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007601 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007602 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7603}
7604
7605// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7606// DOWN on the window that doesn't have focus. Ensure no window received the
7607// onPointerDownOutsideFocus callback.
7608TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007610 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7611 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007613 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007614
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007615 ASSERT_TRUE(mDispatcher->waitForIdle());
7616 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007617}
7618
7619// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7620// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7621TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007623 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007624 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007625 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007626
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007627 ASSERT_TRUE(mDispatcher->waitForIdle());
7628 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007629}
7630
7631// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7632// DOWN on the window that already has focus. Ensure no window received the
7633// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007634TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007636 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007637 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007639 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007640
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007641 ASSERT_TRUE(mDispatcher->waitForIdle());
7642 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007643}
7644
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007645// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7646// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7647TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7648 const MotionEvent event =
7649 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7650 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007651 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007652 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7653 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7656 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7657
7658 ASSERT_TRUE(mDispatcher->waitForIdle());
7659 mFakePolicy->assertOnPointerDownWasNotCalled();
7660 // Ensure that the unfocused window did not receive any FOCUS events.
7661 mUnfocusedWindow->assertNoEvents();
7662}
7663
chaviwaf87b3e2019-10-01 16:59:28 -07007664// These tests ensures we can send touch events to a single client when there are multiple input
7665// windows that point to the same client token.
7666class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7667 virtual void SetUp() override {
7668 InputDispatcherTest::SetUp();
7669
Chris Yea209fde2020-07-22 13:54:51 -07007670 std::shared_ptr<FakeApplicationHandle> application =
7671 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007672 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7673 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007674 mWindow1->setFrame(Rect(0, 0, 100, 100));
7675
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007676 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
7677 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07007678 mWindow2->setFrame(Rect(100, 100, 200, 200));
7679
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007680 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007681 }
7682
7683protected:
7684 sp<FakeWindowHandle> mWindow1;
7685 sp<FakeWindowHandle> mWindow2;
7686
7687 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007688 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007689 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7690 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007691 }
7692
7693 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7694 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007695 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007696 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007697 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007698 ASSERT_NE(nullptr, motionEvent);
7699 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007700
7701 for (size_t i = 0; i < points.size(); i++) {
7702 float expectedX = points[i].x;
7703 float expectedY = points[i].y;
7704
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007705 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007706 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007707 << ", got " << motionEvent->getX(i);
7708 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007709 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007710 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007711 }
7712 }
chaviw9eaa22c2020-07-01 16:21:27 -07007713
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007714 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007715 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007716 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7717 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007718
7719 // Always consume from window1 since it's the window that has the InputReceiver
7720 consumeMotionEvent(mWindow1, action, expectedPoints);
7721 }
chaviwaf87b3e2019-10-01 16:59:28 -07007722};
7723
7724TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7725 // Touch Window 1
7726 PointF touchedPoint = {10, 10};
7727 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007728 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007729
7730 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007731 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007732
7733 // Touch Window 2
7734 touchedPoint = {150, 150};
7735 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007736 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007737}
7738
chaviw9eaa22c2020-07-01 16:21:27 -07007739TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7740 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007741 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007742 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007743
7744 // Touch Window 1
7745 PointF touchedPoint = {10, 10};
7746 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007747 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007748 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07007749 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007750
7751 // Touch Window 2
7752 touchedPoint = {150, 150};
7753 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07007754 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
7755 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007756
chaviw9eaa22c2020-07-01 16:21:27 -07007757 // Update the transform so rotation is set
7758 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007759 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007760 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
7761 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007762}
7763
chaviw9eaa22c2020-07-01 16:21:27 -07007764TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007765 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007766 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007767
7768 // Touch Window 1
7769 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7770 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007771 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007772
7773 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007774 touchedPoints.push_back(PointF{150, 150});
7775 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007776 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007777
chaviw9eaa22c2020-07-01 16:21:27 -07007778 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007779 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007780 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007781
chaviw9eaa22c2020-07-01 16:21:27 -07007782 // Update the transform so rotation is set for Window 2
7783 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007784 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007785 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007786 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007787}
7788
chaviw9eaa22c2020-07-01 16:21:27 -07007789TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007790 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007791 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007792
7793 // Touch Window 1
7794 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7795 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007796 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007797
7798 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007799 touchedPoints.push_back(PointF{150, 150});
7800 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007801
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007802 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007803
7804 // Move both windows
7805 touchedPoints = {{20, 20}, {175, 175}};
7806 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7807 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7808
chaviw9eaa22c2020-07-01 16:21:27 -07007809 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007810
chaviw9eaa22c2020-07-01 16:21:27 -07007811 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007812 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007813 expectedPoints.pop_back();
7814
7815 // Touch Window 2
7816 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007817 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07007818 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007819 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007820
7821 // Move both windows
7822 touchedPoints = {{20, 20}, {175, 175}};
7823 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7824 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7825
7826 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007827}
7828
7829TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
7830 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007831 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007832
7833 // Touch Window 1
7834 std::vector<PointF> touchedPoints = {PointF{10, 10}};
7835 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07007836 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007837
7838 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07007839 touchedPoints.push_back(PointF{150, 150});
7840 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007841
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08007842 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007843
7844 // Move both windows
7845 touchedPoints = {{20, 20}, {175, 175}};
7846 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
7847 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
7848
chaviw9eaa22c2020-07-01 16:21:27 -07007849 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00007850}
7851
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007852/**
7853 * When one of the windows is slippery, the touch should not slip into the other window with the
7854 * same input channel.
7855 */
7856TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
7857 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007858 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07007859
7860 // Touch down in window 1
7861 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7862 ADISPLAY_ID_DEFAULT, {{50, 50}}));
7863 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
7864
7865 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
7866 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
7867 // getting generated.
7868 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7869 ADISPLAY_ID_DEFAULT, {{150, 150}}));
7870
7871 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
7872}
7873
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007874/**
7875 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
7876 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
7877 * that the pointer is hovering over may have a different transform.
7878 */
7879TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007880 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007881
7882 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
7884 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7885 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007886 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7887 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007888 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007889 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7890 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
7891 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07007892 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
7893 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
7894 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
7895}
7896
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007897class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
7898 virtual void SetUp() override {
7899 InputDispatcherTest::SetUp();
7900
Chris Yea209fde2020-07-22 13:54:51 -07007901 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007902 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007903 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
7904 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007905 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007906 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07007907 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007908
7909 // Set focused application.
7910 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
7911
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007912 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007913 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007914 mWindow->consumeFocusEvent(true);
7915 }
7916
7917 virtual void TearDown() override {
7918 InputDispatcherTest::TearDown();
7919 mWindow.clear();
7920 }
7921
7922protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007923 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07007924 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007925 sp<FakeWindowHandle> mWindow;
7926 static constexpr PointF WINDOW_LOCATION = {20, 20};
7927
7928 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08007929 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
7930 .x(WINDOW_LOCATION.x)
7931 .y(WINDOW_LOCATION.y);
7932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7933 .pointer(touchingPointer)
7934 .build());
7935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7936 .pointer(touchingPointer)
7937 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007938 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007939
7940 sp<FakeWindowHandle> addSpyWindow() {
7941 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007942 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007943 spy->setTrustedOverlay(true);
7944 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007945 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007946 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007947 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007948 return spy;
7949 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007950};
7951
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007952// Send a tap and respond, which should not cause an ANR.
7953TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
7954 tapOnWindow();
7955 mWindow->consumeMotionDown();
7956 mWindow->consumeMotionUp();
7957 ASSERT_TRUE(mDispatcher->waitForIdle());
7958 mFakePolicy->assertNotifyAnrWasNotCalled();
7959}
7960
7961// Send a regular key and respond, which should not cause an ANR.
7962TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007964 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7965 ASSERT_TRUE(mDispatcher->waitForIdle());
7966 mFakePolicy->assertNotifyAnrWasNotCalled();
7967}
7968
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007969TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
7970 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007971 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007972 mWindow->consumeFocusEvent(false);
7973
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007974 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007975 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7976 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00007977 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05007979 // Key will not go to window because we have no focused window.
7980 // The 'no focused window' ANR timer should start instead.
7981
7982 // Now, the focused application goes away.
7983 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
7984 // The key should get dropped and there should be no ANR.
7985
7986 ASSERT_TRUE(mDispatcher->waitForIdle());
7987 mFakePolicy->assertNotifyAnrWasNotCalled();
7988}
7989
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007990// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007991// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7992// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007993TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007995 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007996 WINDOW_LOCATION));
7997
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007998 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07007999 ASSERT_TRUE(sequenceNum);
8000 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008001 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008002
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008003 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008004 mWindow->consumeMotionEvent(
8005 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008006 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008007 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008008}
8009
8010// Send a key to the app and have the app not respond right away.
8011TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8012 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008014 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008015 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008016 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008017 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008018 ASSERT_TRUE(mDispatcher->waitForIdle());
8019}
8020
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008021// We have a focused application, but no focused window
8022TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008023 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008024 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008025 mWindow->consumeFocusEvent(false);
8026
8027 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008029 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008030 WINDOW_LOCATION));
8031 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8032 mDispatcher->waitForIdle();
8033 mFakePolicy->assertNotifyAnrWasNotCalled();
8034
8035 // Once a focused event arrives, we get an ANR for this application
8036 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8037 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008038 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008039 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008040 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008041 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008042 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008043 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008044 ASSERT_TRUE(mDispatcher->waitForIdle());
8045}
8046
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008047/**
8048 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8049 * there will not be an ANR.
8050 */
8051TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8052 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008053 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008054 mWindow->consumeFocusEvent(false);
8055
8056 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008057 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8058 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008059 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8060 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8061
8062 // Define a valid key down event that is stale (too old).
8063 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008064 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008065 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008066
8067 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8068
8069 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008070 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008071 InputEventInjectionSync::WAIT_FOR_RESULT,
8072 INJECT_EVENT_TIMEOUT, policyFlags);
8073 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8074 << "Injection should fail because the event is stale";
8075
8076 ASSERT_TRUE(mDispatcher->waitForIdle());
8077 mFakePolicy->assertNotifyAnrWasNotCalled();
8078 mWindow->assertNoEvents();
8079}
8080
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008081// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008082// Make sure that we don't notify policy twice about the same ANR.
8083TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008084 const std::chrono::duration appTimeout = 400ms;
8085 mApplication->setDispatchingTimeout(appTimeout);
8086 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8087
Vishnu Nair47074b82020-08-14 11:54:47 -07008088 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008089 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008090 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008091
8092 // Once a focused event arrives, we get an ANR for this application
8093 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8094 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008095 const std::chrono::duration eventInjectionTimeout = 100ms;
8096 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008097 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008098 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008099 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8100 /*allowKeyRepeat=*/false);
8101 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8102 << "result=" << ftl::enum_string(result);
8103 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8104 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8105 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8106 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008107
Vishnu Naire4df8752022-09-08 09:17:55 -07008108 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008109 // ANR should not be raised again. It is up to policy to do that if it desires.
8110 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008111
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008112 // If we now get a focused window, the ANR should stop, but the policy handles that via
8113 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008114 ASSERT_TRUE(mDispatcher->waitForIdle());
8115}
8116
8117// We have a focused application, but no focused window
8118TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008119 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008120 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008121 mWindow->consumeFocusEvent(false);
8122
8123 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008124 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008125
Vishnu Naire4df8752022-09-08 09:17:55 -07008126 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8127 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008128
8129 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008130 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008131 ASSERT_TRUE(mDispatcher->waitForIdle());
8132 mWindow->assertNoEvents();
8133}
8134
8135/**
8136 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8137 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8138 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8139 * the ANR mechanism should still work.
8140 *
8141 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8142 * DOWN event, while not responding on the second one.
8143 */
8144TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8145 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008146 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008147 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8148 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8149 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008150 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008151
8152 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008153 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008154 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8155 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8156 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008157 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008158
8159 // We have now sent down and up. Let's consume first event and then ANR on the second.
8160 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8161 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008162 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008163}
8164
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008165// A spy window can receive an ANR
8166TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8167 sp<FakeWindowHandle> spy = addSpyWindow();
8168
8169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008170 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008171 WINDOW_LOCATION));
8172 mWindow->consumeMotionDown();
8173
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008174 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008175 ASSERT_TRUE(sequenceNum);
8176 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008177 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008178
8179 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008180 spy->consumeMotionEvent(
8181 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008182 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008183 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008184}
8185
8186// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008187// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008188TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8189 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008190
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008192 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008193 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008195
8196 // Stuck on the ACTION_UP
8197 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008198 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008199
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008200 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008201 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008202 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8203 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008204
8205 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8206 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008207 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008208 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008209 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008210}
8211
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008212// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008213// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008214TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8215 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008216
8217 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008218 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8219 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008220
8221 mWindow->consumeMotionDown();
8222 // Stuck on the ACTION_UP
8223 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008224 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008225
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008226 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008227 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008228 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8229 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008230
8231 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8232 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008233 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008234 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008235 spy->assertNoEvents();
8236}
8237
8238TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008239 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008240
Prabir Pradhanfb549072023-10-05 19:17:36 +00008241 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008242
8243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008244 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008245 WINDOW_LOCATION));
8246
8247 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8248 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8249 ASSERT_TRUE(consumeSeq);
8250
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008251 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8252 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008253
8254 monitor.finishEvent(*consumeSeq);
8255 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8256
8257 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008258 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008259}
8260
8261// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8262// process events, you don't get an anr. When the window later becomes unresponsive again, you
8263// get an ANR again.
8264// 1. tap -> block on ACTION_UP -> receive ANR
8265// 2. consume all pending events (= queue becomes healthy again)
8266// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8267TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8268 tapOnWindow();
8269
8270 mWindow->consumeMotionDown();
8271 // Block on ACTION_UP
8272 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008273 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008274 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8275 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008276 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008277 mWindow->assertNoEvents();
8278
8279 tapOnWindow();
8280 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008281 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008282 mWindow->consumeMotionUp();
8283
8284 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008285 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008286 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008287 mWindow->assertNoEvents();
8288}
8289
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008290// If a connection remains unresponsive for a while, make sure policy is only notified once about
8291// it.
8292TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008294 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008295 WINDOW_LOCATION));
8296
8297 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008298 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008299 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008300 // 'notifyConnectionUnresponsive' should only be called once per connection
8301 mFakePolicy->assertNotifyAnrWasNotCalled();
8302 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008303 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008304 mWindow->consumeMotionEvent(
8305 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008306 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008307 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008308 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008309 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008310}
8311
8312/**
8313 * 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 -07008314 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008315 *
8316 * Warning!!!
8317 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8318 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008319 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008320 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8321 *
8322 * If that value changes, this test should also change.
8323 */
8324TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
8325 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008326 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008327
8328 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008329 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008330 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008331 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008332 ASSERT_TRUE(upSequenceNum);
8333 // Don't finish the events yet, and send a key
8334 // Injection will "succeed" because we will eventually give up and send the key to the focused
8335 // window even if motions are still being processed. But because the injection timeout is short,
8336 // we will receive INJECTION_TIMED_OUT as the result.
8337
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008338 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008339 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8340 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008341 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008342 // Key will not be sent to the window, yet, because the window is still processing events
8343 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008344 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
8345 // Rely here on the fact that it uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8346 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8347 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008348
8349 std::this_thread::sleep_for(500ms);
8350 // if we wait long enough though, dispatcher will give up, and still send the key
8351 // to the focused window, even though we have not yet finished the motion event
8352 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8353 mWindow->finishEvent(*downSequenceNum);
8354 mWindow->finishEvent(*upSequenceNum);
8355}
8356
8357/**
8358 * If a window is processing a motion event, and then a key event comes in, the key event should
8359 * not go to the focused window until the motion is processed.
8360 * If then a new motion comes in, then the pending key event should be going to the currently
8361 * focused window right away.
8362 */
8363TEST_F(InputDispatcherSingleWindowAnr,
8364 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
8365 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008366 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008367
8368 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008369 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008370 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008371 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008372 ASSERT_TRUE(upSequenceNum);
8373 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008374 mDispatcher->notifyKey(
8375 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8376 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8377 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008378 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008379 // Make sure the `assertNoEvents` check doesn't take too long. It uses
8380 // CONSUME_TIMEOUT_NO_EVENT_EXPECTED under the hood.
8381 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8382 mWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008383
8384 // Now tap down again. It should cause the pending key to go to the focused window right away.
8385 tapOnWindow();
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008386 mWindow->consumeKeyEvent(WithKeyAction(AKEY_EVENT_ACTION_DOWN)); // it doesn't matter that we
8387 // haven't ack'd the other events yet. We can finish events in any order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008388 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8389 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008390 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8391 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008392 mWindow->assertNoEvents();
8393}
8394
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008395/**
8396 * Send an event to the app and have the app not respond right away.
8397 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8398 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8399 * At some point, the window becomes responsive again.
8400 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8401 */
8402TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8404 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8405 .build());
8406
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008407 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008408 ASSERT_TRUE(sequenceNum);
8409 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8410 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8411
8412 mWindow->finishEvent(*sequenceNum);
8413 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8414 ASSERT_TRUE(mDispatcher->waitForIdle());
8415 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8416
8417 // Now that the window is responsive, let's continue the gesture.
8418 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8419 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8420 .build());
8421
8422 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8423 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8424 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8425 .build());
8426
8427 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8428 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8429 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8430 .build());
8431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8432 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8433 .build());
8434 // We already canceled this pointer, so the window shouldn't get any new events.
8435 mWindow->assertNoEvents();
8436
8437 // Start another one.
8438 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8439 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8440 .build());
8441 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8442}
8443
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008444class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8445 virtual void SetUp() override {
8446 InputDispatcherTest::SetUp();
8447
Chris Yea209fde2020-07-22 13:54:51 -07008448 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008449 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008450 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8451 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008452 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008453 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008454 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008455
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008456 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8457 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008458 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008459 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008460
8461 // Set focused application.
8462 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008463 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008464
8465 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008466 mDispatcher->onWindowInfosChanged(
8467 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008468 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008469 mFocusedWindow->consumeFocusEvent(true);
8470 }
8471
8472 virtual void TearDown() override {
8473 InputDispatcherTest::TearDown();
8474
8475 mUnfocusedWindow.clear();
8476 mFocusedWindow.clear();
8477 }
8478
8479protected:
Chris Yea209fde2020-07-22 13:54:51 -07008480 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008481 sp<FakeWindowHandle> mUnfocusedWindow;
8482 sp<FakeWindowHandle> mFocusedWindow;
8483 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8484 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8485 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8486
8487 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8488
8489 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8490
8491private:
8492 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008494 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008495 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008497 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008498 location));
8499 }
8500};
8501
8502// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8503// should be ANR'd first.
8504TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008506 injectMotionEvent(*mDispatcher,
8507 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8508 AINPUT_SOURCE_TOUCHSCREEN)
8509 .pointer(PointerBuilder(0, ToolType::FINGER)
8510 .x(FOCUSED_WINDOW_LOCATION.x)
8511 .y(FOCUSED_WINDOW_LOCATION.y))
8512 .build()));
8513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8514 injectMotionEvent(*mDispatcher,
8515 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8516 AINPUT_SOURCE_TOUCHSCREEN)
8517 .pointer(PointerBuilder(0, ToolType::FINGER)
8518 .x(FOCUSED_WINDOW_LOCATION.x)
8519 .y(FOCUSED_WINDOW_LOCATION.y))
8520 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008521 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008522 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008523 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008524 // We consumed all events, so no ANR
8525 ASSERT_TRUE(mDispatcher->waitForIdle());
8526 mFakePolicy->assertNotifyAnrWasNotCalled();
8527
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008529 injectMotionEvent(*mDispatcher,
8530 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8531 AINPUT_SOURCE_TOUCHSCREEN)
8532 .pointer(PointerBuilder(0, ToolType::FINGER)
8533 .x(FOCUSED_WINDOW_LOCATION.x)
8534 .y(FOCUSED_WINDOW_LOCATION.y))
8535 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008536 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008537 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008538
8539 const std::chrono::duration timeout =
8540 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008541 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008542
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008543 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008544 mFocusedWindow->consumeMotionDown();
8545 // This cancel is generated because the connection was unresponsive
8546 mFocusedWindow->consumeMotionCancel();
8547 mFocusedWindow->assertNoEvents();
8548 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008549 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008550 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8551 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008552 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008553}
8554
8555// If we have 2 windows with identical timeouts that are both unresponsive,
8556// it doesn't matter which order they should have ANR.
8557// But we should receive ANR for both.
8558TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8559 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008560 mUnfocusedWindow->setDispatchingTimeout(
8561 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008562 mDispatcher->onWindowInfosChanged(
8563 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008564
8565 tapOnFocusedWindow();
8566 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008567 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008568 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8569 mFocusedWindow->getDispatchingTimeout(
8570 DISPATCHING_TIMEOUT)),
8571 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8572
8573 ASSERT_THAT(anrConnectionTokens,
8574 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8575 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008576
8577 ASSERT_TRUE(mDispatcher->waitForIdle());
8578 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008579
8580 mFocusedWindow->consumeMotionDown();
8581 mFocusedWindow->consumeMotionUp();
8582 mUnfocusedWindow->consumeMotionOutside();
8583
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008584 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8585 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008586
8587 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008588 ASSERT_THAT(responsiveTokens,
8589 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8590 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008591 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008592}
8593
8594// If a window is already not responding, the second tap on the same window should be ignored.
8595// We should also log an error to account for the dropped event (not tested here).
8596// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8597TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8598 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008599 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008600 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008601 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008602 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008603 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008604 ASSERT_TRUE(upEventSequenceNum);
8605 const std::chrono::duration timeout =
8606 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008607 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008608
8609 // Tap once again
8610 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008611 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008612 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008613 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008614 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008615 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008616 FOCUSED_WINDOW_LOCATION));
8617 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8618 // valid touch target
8619 mUnfocusedWindow->assertNoEvents();
8620
8621 // Consume the first tap
8622 mFocusedWindow->finishEvent(*downEventSequenceNum);
8623 mFocusedWindow->finishEvent(*upEventSequenceNum);
8624 ASSERT_TRUE(mDispatcher->waitForIdle());
8625 // The second tap did not go to the focused window
8626 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008627 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008628 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8629 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008630 mFakePolicy->assertNotifyAnrWasNotCalled();
8631}
8632
8633// If you tap outside of all windows, there will not be ANR
8634TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008635 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008636 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008637 LOCATION_OUTSIDE_ALL_WINDOWS));
8638 ASSERT_TRUE(mDispatcher->waitForIdle());
8639 mFakePolicy->assertNotifyAnrWasNotCalled();
8640}
8641
8642// Since the focused window is paused, tapping on it should not produce any events
8643TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8644 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008645 mDispatcher->onWindowInfosChanged(
8646 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008647
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008648 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008649 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008650 FOCUSED_WINDOW_LOCATION));
8651
8652 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8653 ASSERT_TRUE(mDispatcher->waitForIdle());
8654 // Should not ANR because the window is paused, and touches shouldn't go to it
8655 mFakePolicy->assertNotifyAnrWasNotCalled();
8656
8657 mFocusedWindow->assertNoEvents();
8658 mUnfocusedWindow->assertNoEvents();
8659}
8660
8661/**
8662 * 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 -07008663 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008664 * If a different window becomes focused at this time, the key should go to that window instead.
8665 *
8666 * Warning!!!
8667 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8668 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008669 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008670 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8671 *
8672 * If that value changes, this test should also change.
8673 */
8674TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8675 // Set a long ANR timeout to prevent it from triggering
8676 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008677 mDispatcher->onWindowInfosChanged(
8678 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008679
8680 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008681 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008682 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008683 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008684 ASSERT_TRUE(upSequenceNum);
8685 // Don't finish the events yet, and send a key
8686 // Injection will succeed because we will eventually give up and send the key to the focused
8687 // window even if motions are still being processed.
8688
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008689 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008690 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8691 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008693 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008694 // and the key remains pending, waiting for the touch events to be processed.
8695 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8696 // under the hood.
8697 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
8698 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008699
8700 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07008701 mFocusedWindow->setFocusable(false);
8702 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008703 mDispatcher->onWindowInfosChanged(
8704 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008705 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008706
8707 // Focus events should precede the key events
8708 mUnfocusedWindow->consumeFocusEvent(true);
8709 mFocusedWindow->consumeFocusEvent(false);
8710
8711 // Finish the tap events, which should unblock dispatcher
8712 mUnfocusedWindow->finishEvent(*downSequenceNum);
8713 mUnfocusedWindow->finishEvent(*upSequenceNum);
8714
8715 // Now that all queues are cleared and no backlog in the connections, the key event
8716 // can finally go to the newly focused "mUnfocusedWindow".
8717 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8718 mFocusedWindow->assertNoEvents();
8719 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008720 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008721}
8722
8723// When the touch stream is split across 2 windows, and one of them does not respond,
8724// then ANR should be raised and the touch should be canceled for the unresponsive window.
8725// The other window should not be affected by that.
8726TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
8727 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00008728 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8729 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8730 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008731 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008732
8733 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00008734 mDispatcher->notifyMotion(
8735 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8736 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008737
8738 const std::chrono::duration timeout =
8739 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008740 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008741
8742 mUnfocusedWindow->consumeMotionDown();
8743 mFocusedWindow->consumeMotionDown();
8744 // Focused window may or may not receive ACTION_MOVE
8745 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008746 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008747 ASSERT_TRUE(moveOrCancelSequenceNum);
8748 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
8749 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008750 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008751 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
8752 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
8753 mFocusedWindow->consumeMotionCancel();
8754 } else {
8755 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
8756 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008757 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008758 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8759 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008760
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008761 mUnfocusedWindow->assertNoEvents();
8762 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008763 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008764}
8765
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008766/**
8767 * If we have no focused window, and a key comes in, we start the ANR timer.
8768 * The focused application should add a focused window before the timer runs out to prevent ANR.
8769 *
8770 * If the user touches another application during this time, the key should be dropped.
8771 * Next, if a new focused window comes in, without toggling the focused application,
8772 * then no ANR should occur.
8773 *
8774 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
8775 * but in some cases the policy may not update the focused application.
8776 */
8777TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
8778 std::shared_ptr<FakeApplicationHandle> focusedApplication =
8779 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07008780 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008781 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
8782 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
8783 mFocusedWindow->setFocusable(false);
8784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008785 mDispatcher->onWindowInfosChanged(
8786 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008787 mFocusedWindow->consumeFocusEvent(false);
8788
8789 // Send a key. The ANR timer should start because there is no focused window.
8790 // 'focusedApplication' will get blamed if this timer completes.
8791 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008792 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008793 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8794 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00008795 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008797
8798 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
8799 // then the injected touches won't cause the focused event to get dropped.
8800 // The dispatcher only checks for whether the queue should be pruned upon queueing.
8801 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
8802 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
8803 // For this test, it means that the key would get delivered to the window once it becomes
8804 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008805 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008806
8807 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00008808 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8809 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8810 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008811
8812 // We do not consume the motion right away, because that would require dispatcher to first
8813 // process (== drop) the key event, and by that time, ANR will be raised.
8814 // Set the focused window first.
8815 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008816 mDispatcher->onWindowInfosChanged(
8817 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05008818 setFocusedWindow(mFocusedWindow);
8819 mFocusedWindow->consumeFocusEvent(true);
8820 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
8821 // to another application. This could be a bug / behaviour in the policy.
8822
8823 mUnfocusedWindow->consumeMotionDown();
8824
8825 ASSERT_TRUE(mDispatcher->waitForIdle());
8826 // Should not ANR because we actually have a focused window. It was just added too slowly.
8827 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
8828}
8829
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08008830/**
8831 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
8832 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
8833 * dispatcher doesn't prune pointer events incorrectly.
8834 *
8835 * This test reproduces a crash in InputDispatcher.
8836 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
8837 *
8838 * Keep the currently focused application (mApplication), and have no focused window.
8839 * We set up two additional windows:
8840 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
8841 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
8842 * window. This window is not focusable, but is touchable.
8843 *
8844 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
8845 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
8846 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
8847 *
8848 * Now, we touch "Another window". This window is owned by a different application than
8849 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
8850 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
8851 * dropping the events from its queue. Ensure that no crash occurs.
8852 *
8853 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
8854 * This does not affect the test running time.
8855 */
8856TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
8857 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
8858 std::make_shared<FakeApplicationHandle>();
8859 systemUiApplication->setDispatchingTimeout(3000ms);
8860 mFakePolicy->setStaleEventTimeout(3000ms);
8861 sp<FakeWindowHandle> navigationBar =
8862 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
8863 ADISPLAY_ID_DEFAULT);
8864 navigationBar->setFocusable(false);
8865 navigationBar->setWatchOutsideTouch(true);
8866 navigationBar->setFrame(Rect(0, 0, 100, 100));
8867
8868 mApplication->setDispatchingTimeout(3000ms);
8869 // 'mApplication' is already focused, but we call it again here to make it explicit.
8870 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8871
8872 std::shared_ptr<FakeApplicationHandle> anotherApplication =
8873 std::make_shared<FakeApplicationHandle>();
8874 sp<FakeWindowHandle> appWindow =
8875 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
8876 ADISPLAY_ID_DEFAULT);
8877 appWindow->setFocusable(false);
8878 appWindow->setFrame(Rect(100, 100, 200, 200));
8879
8880 mDispatcher->onWindowInfosChanged(
8881 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
8882 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
8883 mFocusedWindow->consumeFocusEvent(false);
8884
8885 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
8886 // in response.
8887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8888 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8889 .build());
8890 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8891
8892 // Key will not be sent anywhere because we have no focused window. It will remain pending.
8893 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
8894 InputEventInjectionResult result =
8895 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8896 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8897 /*allowKeyRepeat=*/false);
8898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8899
8900 // Finish the gesture - lift up finger and inject ACTION_UP key event
8901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8902 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8903 .build());
8904 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8905 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
8906 /*allowKeyRepeat=*/false);
8907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
8908 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
8909 // getting any events yet.
8910 navigationBar->assertNoEvents();
8911
8912 // Now touch "Another window". This touch is going to a different application than the one we
8913 // are waiting for (which is 'mApplication').
8914 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
8915 // trying to be injected) and to continue processing the rest of the events in the original
8916 // order.
8917 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8918 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8919 .build());
8920 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
8921 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
8922 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8923
8924 appWindow->assertNoEvents();
8925 navigationBar->assertNoEvents();
8926}
8927
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008928// These tests ensure we cannot send touch events to a window that's positioned behind a window
8929// that has feature NO_INPUT_CHANNEL.
8930// Layout:
8931// Top (closest to user)
8932// mNoInputWindow (above all windows)
8933// mBottomWindow
8934// Bottom (furthest from user)
8935class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
8936 virtual void SetUp() override {
8937 InputDispatcherTest::SetUp();
8938
8939 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008940 mNoInputWindow =
8941 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8942 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008943 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008944 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008945 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
8946 // It's perfectly valid for this window to not have an associated input channel
8947
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008948 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
8949 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008950 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
8951
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008952 mDispatcher->onWindowInfosChanged(
8953 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008954 }
8955
8956protected:
8957 std::shared_ptr<FakeApplicationHandle> mApplication;
8958 sp<FakeWindowHandle> mNoInputWindow;
8959 sp<FakeWindowHandle> mBottomWindow;
8960};
8961
8962TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
8963 PointF touchedPoint = {10, 10};
8964
Prabir Pradhan678438e2023-04-13 19:32:51 +00008965 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8966 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8967 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008968
8969 mNoInputWindow->assertNoEvents();
8970 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
8971 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
8972 // and therefore should prevent mBottomWindow from receiving touches
8973 mBottomWindow->assertNoEvents();
8974}
8975
8976/**
8977 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
8978 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
8979 */
8980TEST_F(InputDispatcherMultiWindowOcclusionTests,
8981 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008982 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
8983 "Window with input channel and NO_INPUT_CHANNEL",
8984 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008985
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008986 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008987 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008988 mDispatcher->onWindowInfosChanged(
8989 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008990
8991 PointF touchedPoint = {10, 10};
8992
Prabir Pradhan678438e2023-04-13 19:32:51 +00008993 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8994 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8995 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05008996
8997 mNoInputWindow->assertNoEvents();
8998 mBottomWindow->assertNoEvents();
8999}
9000
Vishnu Nair958da932020-08-21 17:12:37 -07009001class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9002protected:
9003 std::shared_ptr<FakeApplicationHandle> mApp;
9004 sp<FakeWindowHandle> mWindow;
9005 sp<FakeWindowHandle> mMirror;
9006
9007 virtual void SetUp() override {
9008 InputDispatcherTest::SetUp();
9009 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009010 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
9011 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
9012 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07009013 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9014 mWindow->setFocusable(true);
9015 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009016 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009017 }
9018};
9019
9020TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9021 // Request focus on a mirrored window
9022 setFocusedWindow(mMirror);
9023
9024 // window gets focused
9025 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009027 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009028 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9029}
9030
9031// A focused & mirrored window remains focused only if the window and its mirror are both
9032// focusable.
9033TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9034 setFocusedWindow(mMirror);
9035
9036 // window gets focused
9037 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009039 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009040 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009042 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009043 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9044
9045 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009046 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009047
9048 // window loses focus since one of the windows associated with the token in not focusable
9049 mWindow->consumeFocusEvent(false);
9050
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009051 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009052 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009053 mWindow->assertNoEvents();
9054}
9055
9056// A focused & mirrored window remains focused until the window and its mirror both become
9057// invisible.
9058TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9059 setFocusedWindow(mMirror);
9060
9061 // window gets focused
9062 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009064 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009065 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009067 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009068 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9069
9070 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009071 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009072
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009074 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009075 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009077 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009078 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9079
9080 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009081 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009082
9083 // window loses focus only after all windows associated with the token become invisible.
9084 mWindow->consumeFocusEvent(false);
9085
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009086 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009087 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009088 mWindow->assertNoEvents();
9089}
9090
9091// A focused & mirrored window remains focused until both windows are removed.
9092TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9093 setFocusedWindow(mMirror);
9094
9095 // window gets focused
9096 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009098 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009099 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009101 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009102 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9103
9104 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009105 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009106
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009108 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009109 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009111 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009112 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9113
9114 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009115 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009116 mWindow->consumeFocusEvent(false);
9117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009118 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009119 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009120 mWindow->assertNoEvents();
9121}
9122
9123// Focus request can be pending until one window becomes visible.
9124TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9125 // Request focus on an invisible mirror.
9126 mWindow->setVisible(false);
9127 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009128 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009129 setFocusedWindow(mMirror);
9130
9131 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009133 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9134 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009135
9136 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009137 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009138
9139 // window gets focused
9140 mWindow->consumeFocusEvent(true);
9141 // window gets the pending key event
9142 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9143}
Prabir Pradhan99987712020-11-10 18:43:05 -08009144
9145class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9146protected:
9147 std::shared_ptr<FakeApplicationHandle> mApp;
9148 sp<FakeWindowHandle> mWindow;
9149 sp<FakeWindowHandle> mSecondWindow;
9150
9151 void SetUp() override {
9152 InputDispatcherTest::SetUp();
9153 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009154 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009155 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009156 mSecondWindow =
9157 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009158 mSecondWindow->setFocusable(true);
9159
9160 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009161 mDispatcher->onWindowInfosChanged(
9162 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009163
9164 setFocusedWindow(mWindow);
9165 mWindow->consumeFocusEvent(true);
9166 }
9167
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009168 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009169 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009170 }
9171
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009172 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9173 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009174 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009175 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9176 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009177 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009178 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009179 }
9180};
9181
9182TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9183 // Ensure that capture cannot be obtained for unfocused windows.
9184 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9185 mFakePolicy->assertSetPointerCaptureNotCalled();
9186 mSecondWindow->assertNoEvents();
9187
9188 // Ensure that capture can be enabled from the focus window.
9189 requestAndVerifyPointerCapture(mWindow, true);
9190
9191 // Ensure that capture cannot be disabled from a window that does not have capture.
9192 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9193 mFakePolicy->assertSetPointerCaptureNotCalled();
9194
9195 // Ensure that capture can be disabled from the window with capture.
9196 requestAndVerifyPointerCapture(mWindow, false);
9197}
9198
9199TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009200 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009201
9202 setFocusedWindow(mSecondWindow);
9203
9204 // Ensure that the capture disabled event was sent first.
9205 mWindow->consumeCaptureEvent(false);
9206 mWindow->consumeFocusEvent(false);
9207 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009208 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009209
9210 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009211 notifyPointerCaptureChanged({});
9212 notifyPointerCaptureChanged(request);
9213 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009214 mWindow->assertNoEvents();
9215 mSecondWindow->assertNoEvents();
9216 mFakePolicy->assertSetPointerCaptureNotCalled();
9217}
9218
9219TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009220 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009221
9222 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009223 notifyPointerCaptureChanged({});
9224 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009225
9226 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009227 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009228 mWindow->consumeCaptureEvent(false);
9229 mWindow->assertNoEvents();
9230}
9231
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009232TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9233 requestAndVerifyPointerCapture(mWindow, true);
9234
9235 // The first window loses focus.
9236 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009237 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009238 mWindow->consumeCaptureEvent(false);
9239
9240 // Request Pointer Capture from the second window before the notification from InputReader
9241 // arrives.
9242 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009243 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009244
9245 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009246 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009247
9248 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009249 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009250
9251 mSecondWindow->consumeFocusEvent(true);
9252 mSecondWindow->consumeCaptureEvent(true);
9253}
9254
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009255TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9256 // App repeatedly enables and disables capture.
9257 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9258 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9259 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9260 mFakePolicy->assertSetPointerCaptureCalled(false);
9261 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9262 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9263
9264 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9265 // first request is now stale, this should do nothing.
9266 notifyPointerCaptureChanged(firstRequest);
9267 mWindow->assertNoEvents();
9268
9269 // InputReader notifies that the second request was enabled.
9270 notifyPointerCaptureChanged(secondRequest);
9271 mWindow->consumeCaptureEvent(true);
9272}
9273
Prabir Pradhan7092e262022-05-03 16:51:09 +00009274TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9275 requestAndVerifyPointerCapture(mWindow, true);
9276
9277 // App toggles pointer capture off and on.
9278 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9279 mFakePolicy->assertSetPointerCaptureCalled(false);
9280
9281 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9282 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9283
9284 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9285 // preceding "disable" request.
9286 notifyPointerCaptureChanged(enableRequest);
9287
9288 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9289 // any notifications.
9290 mWindow->assertNoEvents();
9291}
9292
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009293/**
9294 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9295 * mouse movements don't affect the previous mouse hovering state.
9296 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9297 * HOVER_MOVE events).
9298 */
9299TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9300 // Mouse hover on the window
9301 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9302 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9303 .build());
9304 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9305 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9306 .build());
9307
9308 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9309 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9310
9311 // Start pointer capture
9312 requestAndVerifyPointerCapture(mWindow, true);
9313
9314 // Send some relative mouse movements and receive them in the window.
9315 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9316 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9317 .build());
9318 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9319 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9320
9321 // Stop pointer capture
9322 requestAndVerifyPointerCapture(mWindow, false);
9323
9324 // Continue hovering on the window
9325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9327 .build());
9328 mWindow->consumeMotionEvent(
9329 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9330
9331 mWindow->assertNoEvents();
9332}
9333
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009334class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9335protected:
9336 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009337
9338 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9339 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9340
9341 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9342 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9343
9344 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9345 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9346 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9347 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9348 MAXIMUM_OBSCURING_OPACITY);
9349
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009350 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9351 static constexpr gui::Uid APP_B_UID{10002};
9352 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009353
9354 sp<FakeWindowHandle> mTouchWindow;
9355
9356 virtual void SetUp() override {
9357 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009358 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009359 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9360 }
9361
9362 virtual void TearDown() override {
9363 InputDispatcherTest::TearDown();
9364 mTouchWindow.clear();
9365 }
9366
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009367 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009368 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009369 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009370 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009371 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009372 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009373 return window;
9374 }
9375
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009376 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009377 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9378 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009379 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009380 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009381 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009382 return window;
9383 }
9384
9385 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009386 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9387 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9388 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009389 }
9390};
9391
9392TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009393 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009394 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009395 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009396
9397 touch();
9398
9399 mTouchWindow->assertNoEvents();
9400}
9401
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009402TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009403 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9404 const sp<FakeWindowHandle>& w =
9405 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009406 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009407
9408 touch();
9409
9410 mTouchWindow->assertNoEvents();
9411}
9412
9413TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009414 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9415 const sp<FakeWindowHandle>& w =
9416 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009417 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009418
9419 touch();
9420
9421 w->assertNoEvents();
9422}
9423
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009424TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009425 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009426 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009427
9428 touch();
9429
9430 mTouchWindow->consumeAnyMotionDown();
9431}
9432
9433TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009434 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009435 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009436 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009437 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009438
9439 touch({PointF{100, 100}});
9440
9441 mTouchWindow->consumeAnyMotionDown();
9442}
9443
9444TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009445 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009446 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009447 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009448
9449 touch();
9450
9451 mTouchWindow->consumeAnyMotionDown();
9452}
9453
9454TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9455 const sp<FakeWindowHandle>& w =
9456 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009457 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009458
9459 touch();
9460
9461 mTouchWindow->consumeAnyMotionDown();
9462}
9463
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009464TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9465 const sp<FakeWindowHandle>& w =
9466 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009467 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009468
9469 touch();
9470
9471 w->assertNoEvents();
9472}
9473
9474/**
9475 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9476 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9477 * window, the occluding window will still receive ACTION_OUTSIDE event.
9478 */
9479TEST_F(InputDispatcherUntrustedTouchesTest,
9480 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9481 const sp<FakeWindowHandle>& w =
9482 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009483 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009484 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009485
9486 touch();
9487
9488 w->consumeMotionOutside();
9489}
9490
9491TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9492 const sp<FakeWindowHandle>& w =
9493 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009494 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009495 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009496
9497 touch();
9498
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009499 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009500}
9501
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009502TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009503 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009504 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9505 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009506 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009507
9508 touch();
9509
9510 mTouchWindow->consumeAnyMotionDown();
9511}
9512
9513TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9514 const sp<FakeWindowHandle>& w =
9515 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9516 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009517 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009518
9519 touch();
9520
9521 mTouchWindow->consumeAnyMotionDown();
9522}
9523
9524TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009525 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009526 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9527 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009528 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009529
9530 touch();
9531
9532 mTouchWindow->assertNoEvents();
9533}
9534
9535TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9536 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9537 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009538 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9539 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009540 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009541 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9542 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009543 mDispatcher->onWindowInfosChanged(
9544 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009545
9546 touch();
9547
9548 mTouchWindow->assertNoEvents();
9549}
9550
9551TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9552 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9553 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009554 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9555 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009556 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009557 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9558 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009559 mDispatcher->onWindowInfosChanged(
9560 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009561
9562 touch();
9563
9564 mTouchWindow->consumeAnyMotionDown();
9565}
9566
9567TEST_F(InputDispatcherUntrustedTouchesTest,
9568 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9569 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009570 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9571 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009572 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009573 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9574 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009575 mDispatcher->onWindowInfosChanged(
9576 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009577
9578 touch();
9579
9580 mTouchWindow->consumeAnyMotionDown();
9581}
9582
9583TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9584 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009585 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9586 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009587 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009588 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9589 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009590 mDispatcher->onWindowInfosChanged(
9591 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009592
9593 touch();
9594
9595 mTouchWindow->assertNoEvents();
9596}
9597
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009598TEST_F(InputDispatcherUntrustedTouchesTest,
9599 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9600 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009601 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9602 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009603 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009604 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9605 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009606 mDispatcher->onWindowInfosChanged(
9607 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009608
9609 touch();
9610
9611 mTouchWindow->assertNoEvents();
9612}
9613
9614TEST_F(InputDispatcherUntrustedTouchesTest,
9615 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9616 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009617 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9618 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009619 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009620 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9621 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009622 mDispatcher->onWindowInfosChanged(
9623 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009624
9625 touch();
9626
9627 mTouchWindow->consumeAnyMotionDown();
9628}
9629
9630TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9631 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009632 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9633 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009634 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009635
9636 touch();
9637
9638 mTouchWindow->consumeAnyMotionDown();
9639}
9640
9641TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9642 const sp<FakeWindowHandle>& w =
9643 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009644 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009645
9646 touch();
9647
9648 mTouchWindow->consumeAnyMotionDown();
9649}
9650
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009651TEST_F(InputDispatcherUntrustedTouchesTest,
9652 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9653 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9654 const sp<FakeWindowHandle>& w =
9655 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009656 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009657
9658 touch();
9659
9660 mTouchWindow->assertNoEvents();
9661}
9662
9663TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9664 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9665 const sp<FakeWindowHandle>& w =
9666 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009667 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009668
9669 touch();
9670
9671 mTouchWindow->consumeAnyMotionDown();
9672}
9673
9674TEST_F(InputDispatcherUntrustedTouchesTest,
9675 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9676 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9677 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009678 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9679 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009680 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009681
9682 touch();
9683
9684 mTouchWindow->consumeAnyMotionDown();
9685}
9686
9687TEST_F(InputDispatcherUntrustedTouchesTest,
9688 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
9689 const sp<FakeWindowHandle>& w1 =
9690 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9691 OPACITY_BELOW_THRESHOLD);
9692 const sp<FakeWindowHandle>& w2 =
9693 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9694 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009695 mDispatcher->onWindowInfosChanged(
9696 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009697
9698 touch();
9699
9700 mTouchWindow->assertNoEvents();
9701}
9702
9703/**
9704 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
9705 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
9706 * (which alone would result in allowing touches) does not affect the blocking behavior.
9707 */
9708TEST_F(InputDispatcherUntrustedTouchesTest,
9709 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
9710 const sp<FakeWindowHandle>& wB =
9711 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
9712 OPACITY_BELOW_THRESHOLD);
9713 const sp<FakeWindowHandle>& wC =
9714 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9715 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009716 mDispatcher->onWindowInfosChanged(
9717 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009718
9719 touch();
9720
9721 mTouchWindow->assertNoEvents();
9722}
9723
9724/**
9725 * This test is testing that a window from a different UID but with same application token doesn't
9726 * block the touch. Apps can share the application token for close UI collaboration for example.
9727 */
9728TEST_F(InputDispatcherUntrustedTouchesTest,
9729 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
9730 const sp<FakeWindowHandle>& w =
9731 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
9732 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009733 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009734
9735 touch();
9736
9737 mTouchWindow->consumeAnyMotionDown();
9738}
9739
arthurhungb89ccb02020-12-30 16:19:01 +08009740class InputDispatcherDragTests : public InputDispatcherTest {
9741protected:
9742 std::shared_ptr<FakeApplicationHandle> mApp;
9743 sp<FakeWindowHandle> mWindow;
9744 sp<FakeWindowHandle> mSecondWindow;
9745 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009746 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009747 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
9748 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08009749
9750 void SetUp() override {
9751 InputDispatcherTest::SetUp();
9752 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009753 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009754 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009755
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009756 mSecondWindow =
9757 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08009758 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08009759
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009760 mSpyWindow =
9761 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009762 mSpyWindow->setSpy(true);
9763 mSpyWindow->setTrustedOverlay(true);
9764 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
9765
arthurhungb89ccb02020-12-30 16:19:01 +08009766 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009767 mDispatcher->onWindowInfosChanged(
9768 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
9769 {},
9770 0,
9771 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009772 }
9773
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009774 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
9775 switch (fromSource) {
9776 case AINPUT_SOURCE_TOUCHSCREEN:
9777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009779 ADISPLAY_ID_DEFAULT, {50, 50}))
9780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9781 break;
9782 case AINPUT_SOURCE_STYLUS:
9783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009784 injectMotionEvent(*mDispatcher,
9785 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9786 AINPUT_SOURCE_STYLUS)
9787 .buttonState(
9788 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
9789 .pointer(PointerBuilder(0, ToolType::STYLUS)
9790 .x(50)
9791 .y(50))
9792 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009793 break;
9794 case AINPUT_SOURCE_MOUSE:
9795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009796 injectMotionEvent(*mDispatcher,
9797 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9798 AINPUT_SOURCE_MOUSE)
9799 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
9800 .pointer(PointerBuilder(MOUSE_POINTER_ID,
9801 ToolType::MOUSE)
9802 .x(50)
9803 .y(50))
9804 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009805 break;
9806 default:
9807 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
9808 }
arthurhungb89ccb02020-12-30 16:19:01 +08009809
9810 // Window should receive motion event.
9811 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009812 // Spy window should also receive motion event
9813 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00009814 }
9815
9816 // Start performing drag, we will create a drag window and transfer touch to it.
9817 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
9818 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009819 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00009820 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009821 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00009822 }
arthurhungb89ccb02020-12-30 16:19:01 +08009823
9824 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009825 mDragWindow =
9826 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009827 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009828 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
9829 *mWindow->getInfo(), *mSecondWindow->getInfo()},
9830 {},
9831 0,
9832 0});
arthurhungb89ccb02020-12-30 16:19:01 +08009833
9834 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00009835 bool transferred =
9836 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00009837 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00009838 if (transferred) {
9839 mWindow->consumeMotionCancel();
9840 mDragWindow->consumeMotionDown();
9841 }
9842 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08009843 }
9844};
9845
9846TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009847 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08009848
9849 // Move on window.
9850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009851 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009852 ADISPLAY_ID_DEFAULT, {50, 50}))
9853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9854 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9855 mWindow->consumeDragEvent(false, 50, 50);
9856 mSecondWindow->assertNoEvents();
9857
9858 // Move to another window.
9859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009860 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009861 ADISPLAY_ID_DEFAULT, {150, 50}))
9862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9863 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9864 mWindow->consumeDragEvent(true, 150, 50);
9865 mSecondWindow->consumeDragEvent(false, 50, 50);
9866
9867 // Move back to original window.
9868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009869 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +08009870 ADISPLAY_ID_DEFAULT, {50, 50}))
9871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9872 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9873 mWindow->consumeDragEvent(false, 50, 50);
9874 mSecondWindow->consumeDragEvent(true, -50, 50);
9875
9876 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009877 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9878 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +08009879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9880 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9881 mWindow->assertNoEvents();
9882 mSecondWindow->assertNoEvents();
9883}
9884
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009885TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009886 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009887
9888 // No cancel event after drag start
9889 mSpyWindow->assertNoEvents();
9890
9891 const MotionEvent secondFingerDownEvent =
9892 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9893 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009894 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9895 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009896 .build();
9897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009898 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00009899 InputEventInjectionSync::WAIT_FOR_RESULT))
9900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9901
9902 // Receives cancel for first pointer after next pointer down
9903 mSpyWindow->consumeMotionCancel();
9904 mSpyWindow->consumeMotionDown();
9905
9906 mSpyWindow->assertNoEvents();
9907}
9908
arthurhungf452d0b2021-01-06 00:19:52 +08009909TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009910 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08009911
9912 // Move on window.
9913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009914 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009915 ADISPLAY_ID_DEFAULT, {50, 50}))
9916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9917 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9918 mWindow->consumeDragEvent(false, 50, 50);
9919 mSecondWindow->assertNoEvents();
9920
9921 // Move to another window.
9922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009923 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +08009924 ADISPLAY_ID_DEFAULT, {150, 50}))
9925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9926 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9927 mWindow->consumeDragEvent(true, 150, 50);
9928 mSecondWindow->consumeDragEvent(false, 50, 50);
9929
9930 // drop to another window.
9931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009932 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +08009933 {150, 50}))
9934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9935 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07009936 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08009937 mWindow->assertNoEvents();
9938 mSecondWindow->assertNoEvents();
9939}
9940
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009941TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
9942 startDrag();
9943
9944 // No cancel event after drag start
9945 mSpyWindow->assertNoEvents();
9946
9947 const MotionEvent secondFingerDownEvent =
9948 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9949 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9950 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9951 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9952 .build();
9953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9954 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9955 InputEventInjectionSync::WAIT_FOR_RESULT))
9956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9957
9958 // Receives cancel for first pointer after next pointer down
9959 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -08009960 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009961 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9962
9963 mSpyWindow->assertNoEvents();
9964
9965 // Spy window calls pilfer pointers
9966 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
9967 mDragWindow->assertNoEvents();
9968
9969 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009970 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009971 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
9972 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
9973 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
9974 .build();
9975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -08009976 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +00009977 InputEventInjectionSync::WAIT_FOR_RESULT))
9978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9979
9980 // Drag window should still receive the new event
9981 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
9982 mDragWindow->assertNoEvents();
9983}
9984
arthurhung6d4bed92021-03-17 11:59:33 +08009985TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00009986 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08009987
9988 // Move on window and keep button pressed.
9989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009990 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +08009991 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
9992 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009993 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08009994 .build()))
9995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9996 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
9997 mWindow->consumeDragEvent(false, 50, 50);
9998 mSecondWindow->assertNoEvents();
9999
10000 // Move to another window and release button, expect to drop item.
10001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010002 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010003 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10004 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010005 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010006 .build()))
10007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10008 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10009 mWindow->assertNoEvents();
10010 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010011 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010012
10013 // nothing to the window.
10014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010015 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010016 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10017 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010018 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010019 .build()))
10020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10021 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10022 mWindow->assertNoEvents();
10023 mSecondWindow->assertNoEvents();
10024}
10025
Arthur Hung54745652022-04-20 07:17:41 +000010026TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010027 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010028
10029 // Set second window invisible.
10030 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010031 mDispatcher->onWindowInfosChanged(
10032 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010033
10034 // Move on window.
10035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010036 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010037 ADISPLAY_ID_DEFAULT, {50, 50}))
10038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10039 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10040 mWindow->consumeDragEvent(false, 50, 50);
10041 mSecondWindow->assertNoEvents();
10042
10043 // Move to another window.
10044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010045 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010046 ADISPLAY_ID_DEFAULT, {150, 50}))
10047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10048 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10049 mWindow->consumeDragEvent(true, 150, 50);
10050 mSecondWindow->assertNoEvents();
10051
10052 // drop to another window.
10053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010054 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010055 {150, 50}))
10056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10057 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010058 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010059 mWindow->assertNoEvents();
10060 mSecondWindow->assertNoEvents();
10061}
10062
Arthur Hung54745652022-04-20 07:17:41 +000010063TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010064 // Ensure window could track pointerIds if it didn't support split touch.
10065 mWindow->setPreventSplitting(true);
10066
Arthur Hung54745652022-04-20 07:17:41 +000010067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010068 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010069 {50, 50}))
10070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10071 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10072
10073 const MotionEvent secondFingerDownEvent =
10074 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10075 .displayId(ADISPLAY_ID_DEFAULT)
10076 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010077 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10078 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010079 .build();
10080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010081 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010082 InputEventInjectionSync::WAIT_FOR_RESULT))
10083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010084 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010085
10086 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010087 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010088}
10089
10090TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10091 // First down on second window.
10092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010093 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010094 {150, 50}))
10095 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10096
10097 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10098
10099 // Second down on first window.
10100 const MotionEvent secondFingerDownEvent =
10101 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10102 .displayId(ADISPLAY_ID_DEFAULT)
10103 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010104 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10105 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010106 .build();
10107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010108 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010109 InputEventInjectionSync::WAIT_FOR_RESULT))
10110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10111 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10112
10113 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010114 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010115
10116 // Move on window.
10117 const MotionEvent secondFingerMoveEvent =
10118 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10119 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010120 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10121 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010122 .build();
10123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010124 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010125 InputEventInjectionSync::WAIT_FOR_RESULT));
10126 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10127 mWindow->consumeDragEvent(false, 50, 50);
10128 mSecondWindow->consumeMotionMove();
10129
10130 // Release the drag pointer should perform drop.
10131 const MotionEvent secondFingerUpEvent =
10132 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10133 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010134 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10135 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010136 .build();
10137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010138 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010139 InputEventInjectionSync::WAIT_FOR_RESULT));
10140 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010141 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010142 mWindow->assertNoEvents();
10143 mSecondWindow->consumeMotionMove();
10144}
10145
Arthur Hung3915c1f2022-05-31 07:17:17 +000010146TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010147 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010148
10149 // Update window of second display.
10150 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010151 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010152 mDispatcher->onWindowInfosChanged(
10153 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10154 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10155 {},
10156 0,
10157 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010158
10159 // Let second display has a touch state.
10160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010161 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010162 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10163 AINPUT_SOURCE_TOUCHSCREEN)
10164 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010165 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010166 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010167 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010168 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010169 mDispatcher->onWindowInfosChanged(
10170 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10171 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10172 {},
10173 0,
10174 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010175
10176 // Move on window.
10177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010178 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010179 ADISPLAY_ID_DEFAULT, {50, 50}))
10180 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10181 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10182 mWindow->consumeDragEvent(false, 50, 50);
10183 mSecondWindow->assertNoEvents();
10184
10185 // Move to another window.
10186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010187 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010188 ADISPLAY_ID_DEFAULT, {150, 50}))
10189 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10190 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10191 mWindow->consumeDragEvent(true, 150, 50);
10192 mSecondWindow->consumeDragEvent(false, 50, 50);
10193
10194 // drop to another window.
10195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010196 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010197 {150, 50}))
10198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10199 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010200 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010201 mWindow->assertNoEvents();
10202 mSecondWindow->assertNoEvents();
10203}
10204
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010205TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10206 startDrag(true, AINPUT_SOURCE_MOUSE);
10207 // Move on window.
10208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010209 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010210 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10211 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010212 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010213 .x(50)
10214 .y(50))
10215 .build()))
10216 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10217 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10218 mWindow->consumeDragEvent(false, 50, 50);
10219 mSecondWindow->assertNoEvents();
10220
10221 // Move to another window.
10222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010223 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010224 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10225 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010226 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010227 .x(150)
10228 .y(50))
10229 .build()))
10230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10231 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10232 mWindow->consumeDragEvent(true, 150, 50);
10233 mSecondWindow->consumeDragEvent(false, 50, 50);
10234
10235 // drop to another window.
10236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010237 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010238 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10239 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010240 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010241 .x(150)
10242 .y(50))
10243 .build()))
10244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10245 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010246 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010247 mWindow->assertNoEvents();
10248 mSecondWindow->assertNoEvents();
10249}
10250
Linnan Li5af92f92023-07-14 14:36:22 +080010251/**
10252 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10253 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10254 */
10255TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10256 // Down on second window
10257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10259 {150, 50}))
10260 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10261
10262 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10263 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10264
10265 // Down on first window
10266 const MotionEvent secondFingerDownEvent =
10267 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10268 .displayId(ADISPLAY_ID_DEFAULT)
10269 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10270 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10271 .build();
10272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10273 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10274 InputEventInjectionSync::WAIT_FOR_RESULT))
10275 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10276 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10277 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10278 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10279
10280 // Start drag on first window
10281 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10282
10283 // Trigger cancel
10284 mDispatcher->cancelCurrentTouch();
10285 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10286 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10287 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10288
10289 ASSERT_TRUE(mDispatcher->waitForIdle());
10290 // The D&D finished with nullptr
10291 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10292
10293 // Remove drag window
10294 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10295
10296 // Inject a simple gesture, ensure dispatcher not crashed
10297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10298 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10299 PointF{50, 50}))
10300 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10301 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10302
10303 const MotionEvent moveEvent =
10304 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10305 .displayId(ADISPLAY_ID_DEFAULT)
10306 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10307 .build();
10308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10309 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10310 InputEventInjectionSync::WAIT_FOR_RESULT))
10311 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10312 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10313
10314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10315 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10316 {50, 50}))
10317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10318 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10319}
10320
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010321TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10322 // Start hovering over the window.
10323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10324 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10325 ADISPLAY_ID_DEFAULT, {50, 50}));
10326
10327 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10328 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10329
10330 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10331 << "Drag and drop should not work with a hovering pointer";
10332}
10333
Vishnu Nair062a8672021-09-03 16:07:44 -070010334class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10335
10336TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10337 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010338 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10339 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010340 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010341 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10342 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010343 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010344 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010345 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010346
10347 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010348 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010349 window->assertNoEvents();
10350
Prabir Pradhan678438e2023-04-13 19:32:51 +000010351 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10352 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010353 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10354 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010355 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010356 window->assertNoEvents();
10357
10358 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010359 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010360 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010361
Prabir Pradhan678438e2023-04-13 19:32:51 +000010362 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010363 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10364
Prabir Pradhan678438e2023-04-13 19:32:51 +000010365 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10366 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010367 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10368 window->assertNoEvents();
10369}
10370
10371TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10372 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10373 std::make_shared<FakeApplicationHandle>();
10374 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010375 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10376 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010377 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010378 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010379 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010381 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10382 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010383 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010384 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010385 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10386 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010387 mDispatcher->onWindowInfosChanged(
10388 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010389 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010390 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010391
10392 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010393 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010394 window->assertNoEvents();
10395
Prabir Pradhan678438e2023-04-13 19:32:51 +000010396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10397 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010398 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10399 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010400 window->assertNoEvents();
10401
10402 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010403 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010404 mDispatcher->onWindowInfosChanged(
10405 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010406
Prabir Pradhan678438e2023-04-13 19:32:51 +000010407 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010408 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10409
Prabir Pradhan678438e2023-04-13 19:32:51 +000010410 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10411 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010412 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10413 window->assertNoEvents();
10414}
10415
10416TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10417 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10418 std::make_shared<FakeApplicationHandle>();
10419 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010420 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10421 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010422 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010423 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010424 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010425 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010426 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10427 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010428 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010429 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010430 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10431 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010432 mDispatcher->onWindowInfosChanged(
10433 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010434 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010435 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010436
10437 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010438 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010439 window->assertNoEvents();
10440
Prabir Pradhan678438e2023-04-13 19:32:51 +000010441 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10442 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10444 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010445 window->assertNoEvents();
10446
10447 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010448 mDispatcher->onWindowInfosChanged(
10449 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010450
Prabir Pradhan678438e2023-04-13 19:32:51 +000010451 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010452 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10453
Prabir Pradhan678438e2023-04-13 19:32:51 +000010454 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10455 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010456 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10457 window->assertNoEvents();
10458}
10459
Antonio Kantekf16f2832021-09-28 04:39:20 +000010460class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10461protected:
10462 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010463 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010464 sp<FakeWindowHandle> mWindow;
10465 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010466 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010467
10468 void SetUp() override {
10469 InputDispatcherTest::SetUp();
10470
10471 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010472 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010473 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010474 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010475 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010476 mSecondWindow =
10477 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010478 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010479 mThirdWindow =
10480 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10481 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10482 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010483
10484 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010485 mDispatcher->onWindowInfosChanged(
10486 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10487 {},
10488 0,
10489 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010490 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010491 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010492
Antonio Kantek15beb512022-06-13 22:35:41 +000010493 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010494 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010495 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010496 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10497 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010498 mThirdWindow->assertNoEvents();
10499 }
10500
10501 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10502 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010503 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010504 SECOND_DISPLAY_ID)) {
10505 mWindow->assertNoEvents();
10506 mSecondWindow->assertNoEvents();
10507 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010508 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010509 }
10510
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010511 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010512 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010513 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10514 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010515 mWindow->consumeTouchModeEvent(inTouchMode);
10516 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010517 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010518 }
10519};
10520
Antonio Kantek26defcf2022-02-08 01:12:27 +000010521TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010522 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010523 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10524 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010525 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010526}
10527
Antonio Kantek26defcf2022-02-08 01:12:27 +000010528TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10529 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010530 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010531 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010532 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010533 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010534 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010535 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010536 mWindow->assertNoEvents();
10537 mSecondWindow->assertNoEvents();
10538}
10539
10540TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10541 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010542 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010543 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010544 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010545 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010546 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010547}
10548
Antonio Kantekf16f2832021-09-28 04:39:20 +000010549TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010550 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010551 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10552 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010553 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010554 mWindow->assertNoEvents();
10555 mSecondWindow->assertNoEvents();
10556}
10557
Antonio Kantek15beb512022-06-13 22:35:41 +000010558TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10559 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10560 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10561 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010562 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010563 mWindow->assertNoEvents();
10564 mSecondWindow->assertNoEvents();
10565 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10566}
10567
Antonio Kantek48710e42022-03-24 14:19:30 -070010568TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10569 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10571 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010572 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10573 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10574
10575 // Then remove focus.
10576 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010577 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010578
10579 // Assert that caller can switch touch mode by owning one of the last interacted window.
10580 const WindowInfo& windowInfo = *mWindow->getInfo();
10581 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10582 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010583 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010584}
10585
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010586class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10587public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010588 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010589 std::shared_ptr<FakeApplicationHandle> application =
10590 std::make_shared<FakeApplicationHandle>();
10591 std::string name = "Fake Spy ";
10592 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010593 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10594 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010595 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010596 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010597 return spy;
10598 }
10599
10600 sp<FakeWindowHandle> createForeground() {
10601 std::shared_ptr<FakeApplicationHandle> application =
10602 std::make_shared<FakeApplicationHandle>();
10603 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010604 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10605 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010606 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010607 return window;
10608 }
10609
10610private:
10611 int mSpyCount{0};
10612};
10613
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010614using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010615/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010616 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10617 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010618TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010619 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010620 ScopedSilentDeath _silentDeath;
10621
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010622 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010623 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010624 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010625 ".* not a trusted overlay");
10626}
10627
10628/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010629 * Input injection into a display with a spy window but no foreground windows should succeed.
10630 */
10631TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010632 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010633 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010634
10635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010636 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10638 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10639}
10640
10641/**
10642 * Verify the order in which different input windows receive events. The touched foreground window
10643 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10644 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10645 * receive events before ones belows it.
10646 *
10647 * Here, we set up a scenario with four windows in the following Z order from the top:
10648 * spy1, spy2, window, spy3.
10649 * We then inject an event and verify that the foreground "window" receives it first, followed by
10650 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10651 * window.
10652 */
10653TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10654 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010655 auto spy1 = createSpy();
10656 auto spy2 = createSpy();
10657 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010658 mDispatcher->onWindowInfosChanged(
10659 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010660 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10661 const size_t numChannels = channels.size();
10662
Michael Wright8e9a8562022-02-09 13:44:29 +000010663 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010664 if (!epollFd.ok()) {
10665 FAIL() << "Failed to create epoll fd";
10666 }
10667
10668 for (size_t i = 0; i < numChannels; i++) {
10669 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10670 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10671 FAIL() << "Failed to add fd to epoll";
10672 }
10673 }
10674
10675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010676 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10678
10679 std::vector<size_t> eventOrder;
10680 std::vector<struct epoll_event> events(numChannels);
10681 for (;;) {
10682 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
10683 (100ms).count());
10684 if (nFds < 0) {
10685 FAIL() << "Failed to call epoll_wait";
10686 }
10687 if (nFds == 0) {
10688 break; // epoll_wait timed out
10689 }
10690 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070010691 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070010692 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010693 channels[i]->consumeMotionDown();
10694 }
10695 }
10696
10697 // Verify the order in which the events were received.
10698 EXPECT_EQ(3u, eventOrder.size());
10699 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
10700 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
10701 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
10702}
10703
10704/**
10705 * A spy window using the NOT_TOUCHABLE flag does not receive events.
10706 */
10707TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
10708 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010709 auto spy = createSpy();
10710 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010711 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010712
10713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010714 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10716 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10717 spy->assertNoEvents();
10718}
10719
10720/**
10721 * A spy window will only receive gestures that originate within its touchable region. Gestures that
10722 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
10723 * to the window.
10724 */
10725TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
10726 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010727 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010728 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010729 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010730
10731 // Inject an event outside the spy window's touchable region.
10732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010733 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10735 window->consumeMotionDown();
10736 spy->assertNoEvents();
10737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010738 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10740 window->consumeMotionUp();
10741 spy->assertNoEvents();
10742
10743 // Inject an event inside the spy window's touchable region.
10744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010745 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010746 {5, 10}))
10747 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10748 window->consumeMotionDown();
10749 spy->consumeMotionDown();
10750}
10751
10752/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010753 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010754 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010755 */
10756TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
10757 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010758 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010759 auto spy = createSpy();
10760 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010761 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010762 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010763 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010764
10765 // Inject an event outside the spy window's frame and touchable region.
10766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010767 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010768 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010769 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10770 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010771 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010772}
10773
10774/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010775 * Even when a spy window spans over multiple foreground windows, the spy should receive all
10776 * pointers that are down within its bounds.
10777 */
10778TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
10779 auto windowLeft = createForeground();
10780 windowLeft->setFrame({0, 0, 100, 200});
10781 auto windowRight = createForeground();
10782 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010783 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010784 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010785 mDispatcher->onWindowInfosChanged(
10786 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010787
10788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010790 {50, 50}))
10791 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10792 windowLeft->consumeMotionDown();
10793 spy->consumeMotionDown();
10794
10795 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010796 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010797 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010798 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10799 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010800 .build();
10801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010802 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010803 InputEventInjectionSync::WAIT_FOR_RESULT))
10804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10805 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000010806 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010807}
10808
10809/**
10810 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
10811 * the spy should receive the second pointer with ACTION_DOWN.
10812 */
10813TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
10814 auto window = createForeground();
10815 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010816 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010817 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010818 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010819
10820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010821 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010822 {50, 50}))
10823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10824 window->consumeMotionDown();
10825 spyRight->assertNoEvents();
10826
10827 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010828 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010829 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010830 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10831 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010832 .build();
10833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010834 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010835 InputEventInjectionSync::WAIT_FOR_RESULT))
10836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010837 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010838 spyRight->consumeMotionDown();
10839}
10840
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010841/**
10842 * The spy window should not be able to affect whether or not touches are split. Only the foreground
10843 * windows should be allowed to control split touch.
10844 */
10845TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010846 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010847 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010848 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080010849 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010850
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010851 auto window = createForeground();
10852 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010854 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010855
10856 // First finger down, no window touched.
10857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010859 {100, 200}))
10860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10861 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10862 window->assertNoEvents();
10863
10864 // Second finger down on window, the window should receive touch down.
10865 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080010866 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010867 .displayId(ADISPLAY_ID_DEFAULT)
10868 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010869 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10870 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010871 .build();
10872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010873 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010874 InputEventInjectionSync::WAIT_FOR_RESULT))
10875 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10876
10877 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000010878 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010879}
10880
10881/**
10882 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
10883 * do not receive key events.
10884 */
10885TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010886 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010887 spy->setFocusable(false);
10888
10889 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010890 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010891 setFocusedWindow(window);
10892 window->consumeFocusEvent(true);
10893
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010895 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10896 window->consumeKeyDown(ADISPLAY_ID_NONE);
10897
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010899 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10900 window->consumeKeyUp(ADISPLAY_ID_NONE);
10901
10902 spy->assertNoEvents();
10903}
10904
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010905using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
10906
10907/**
10908 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
10909 * are currently sent to any other windows - including other spy windows - will also be cancelled.
10910 */
10911TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
10912 auto window = createForeground();
10913 auto spy1 = createSpy();
10914 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010915 mDispatcher->onWindowInfosChanged(
10916 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010917
10918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10921 window->consumeMotionDown();
10922 spy1->consumeMotionDown();
10923 spy2->consumeMotionDown();
10924
10925 // Pilfer pointers from the second spy window.
10926 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
10927 spy2->assertNoEvents();
10928 spy1->consumeMotionCancel();
10929 window->consumeMotionCancel();
10930
10931 // The rest of the gesture should only be sent to the second spy window.
10932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010933 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010934 ADISPLAY_ID_DEFAULT))
10935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10936 spy2->consumeMotionMove();
10937 spy1->assertNoEvents();
10938 window->assertNoEvents();
10939}
10940
10941/**
10942 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
10943 * in the middle of the gesture.
10944 */
10945TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
10946 auto window = createForeground();
10947 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010948 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010949
10950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010951 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010952 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10953 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10954 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10955
10956 window->releaseChannel();
10957
10958 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10959
10960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010961 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10963 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10964}
10965
10966/**
10967 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
10968 * the spy, but not to any other windows.
10969 */
10970TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
10971 auto spy = createSpy();
10972 auto window = createForeground();
10973
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010974 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010975
10976 // First finger down on the window and the spy.
10977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010979 {100, 200}))
10980 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10981 spy->consumeMotionDown();
10982 window->consumeMotionDown();
10983
10984 // Spy window pilfers the pointers.
10985 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
10986 window->consumeMotionCancel();
10987
10988 // Second finger down on the window and spy, but the window should not receive the pointer down.
10989 const MotionEvent secondFingerDownEvent =
10990 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10991 .displayId(ADISPLAY_ID_DEFAULT)
10992 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010993 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
10994 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010995 .build();
10996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010997 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000010998 InputEventInjectionSync::WAIT_FOR_RESULT))
10999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11000
Harry Cutts33476232023-01-30 19:57:29 +000011001 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011002
11003 // Third finger goes down outside all windows, so injection should fail.
11004 const MotionEvent thirdFingerDownEvent =
11005 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11006 .displayId(ADISPLAY_ID_DEFAULT)
11007 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011008 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11009 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11010 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011011 .build();
11012 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011013 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011014 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011015 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011016
11017 spy->assertNoEvents();
11018 window->assertNoEvents();
11019}
11020
11021/**
11022 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11023 */
11024TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11025 auto spy = createSpy();
11026 spy->setFrame(Rect(0, 0, 100, 100));
11027 auto window = createForeground();
11028 window->setFrame(Rect(0, 0, 200, 200));
11029
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011030 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011031
11032 // First finger down on the window only
11033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011034 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011035 {150, 150}))
11036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11037 window->consumeMotionDown();
11038
11039 // Second finger down on the spy and window
11040 const MotionEvent secondFingerDownEvent =
11041 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11042 .displayId(ADISPLAY_ID_DEFAULT)
11043 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011044 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11045 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011046 .build();
11047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011048 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011049 InputEventInjectionSync::WAIT_FOR_RESULT))
11050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11051 spy->consumeMotionDown();
11052 window->consumeMotionPointerDown(1);
11053
11054 // Third finger down on the spy and window
11055 const MotionEvent thirdFingerDownEvent =
11056 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11057 .displayId(ADISPLAY_ID_DEFAULT)
11058 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011059 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11060 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11061 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011062 .build();
11063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011064 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011065 InputEventInjectionSync::WAIT_FOR_RESULT))
11066 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11067 spy->consumeMotionPointerDown(1);
11068 window->consumeMotionPointerDown(2);
11069
11070 // Spy window pilfers the pointers.
11071 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011072 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11073 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011074
11075 spy->assertNoEvents();
11076 window->assertNoEvents();
11077}
11078
11079/**
11080 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11081 * other windows should be canceled. If this results in the cancellation of all pointers for some
11082 * window, then that window should receive ACTION_CANCEL.
11083 */
11084TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11085 auto spy = createSpy();
11086 spy->setFrame(Rect(0, 0, 100, 100));
11087 auto window = createForeground();
11088 window->setFrame(Rect(0, 0, 200, 200));
11089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011090 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011091
11092 // First finger down on both spy and window
11093 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011094 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011095 {10, 10}))
11096 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11097 window->consumeMotionDown();
11098 spy->consumeMotionDown();
11099
11100 // Second finger down on the spy and window
11101 const MotionEvent secondFingerDownEvent =
11102 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11103 .displayId(ADISPLAY_ID_DEFAULT)
11104 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011105 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11106 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011107 .build();
11108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011109 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011110 InputEventInjectionSync::WAIT_FOR_RESULT))
11111 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11112 spy->consumeMotionPointerDown(1);
11113 window->consumeMotionPointerDown(1);
11114
11115 // Spy window pilfers the pointers.
11116 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11117 window->consumeMotionCancel();
11118
11119 spy->assertNoEvents();
11120 window->assertNoEvents();
11121}
11122
11123/**
11124 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11125 * be sent to other windows
11126 */
11127TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11128 auto spy = createSpy();
11129 spy->setFrame(Rect(0, 0, 100, 100));
11130 auto window = createForeground();
11131 window->setFrame(Rect(0, 0, 200, 200));
11132
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011133 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011134
11135 // First finger down on both window and spy
11136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011137 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011138 {10, 10}))
11139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11140 window->consumeMotionDown();
11141 spy->consumeMotionDown();
11142
11143 // Spy window pilfers the pointers.
11144 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11145 window->consumeMotionCancel();
11146
11147 // Second finger down on the window only
11148 const MotionEvent secondFingerDownEvent =
11149 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11150 .displayId(ADISPLAY_ID_DEFAULT)
11151 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011152 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11153 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011154 .build();
11155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011156 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011157 InputEventInjectionSync::WAIT_FOR_RESULT))
11158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11159 window->consumeMotionDown();
11160 window->assertNoEvents();
11161
11162 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11163 spy->consumeMotionMove();
11164 spy->assertNoEvents();
11165}
11166
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011167/**
11168 * A window on the left and a window on the right. Also, a spy window that's above all of the
11169 * windows, and spanning both left and right windows.
11170 * Send simultaneous motion streams from two different devices, one to the left window, and another
11171 * to the right window.
11172 * Pilfer from spy window.
11173 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11174 */
11175TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11176 sp<FakeWindowHandle> spy = createSpy();
11177 spy->setFrame(Rect(0, 0, 200, 200));
11178 sp<FakeWindowHandle> leftWindow = createForeground();
11179 leftWindow->setFrame(Rect(0, 0, 100, 100));
11180
11181 sp<FakeWindowHandle> rightWindow = createForeground();
11182 rightWindow->setFrame(Rect(100, 0, 200, 100));
11183
11184 constexpr int32_t stylusDeviceId = 1;
11185 constexpr int32_t touchDeviceId = 2;
11186
11187 mDispatcher->onWindowInfosChanged(
11188 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11189
11190 // Stylus down on left window and spy
11191 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11192 .deviceId(stylusDeviceId)
11193 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11194 .build());
11195 leftWindow->consumeMotionEvent(
11196 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11197 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11198
11199 // Finger down on right window and spy - but spy already has stylus
11200 mDispatcher->notifyMotion(
11201 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11202 .deviceId(touchDeviceId)
11203 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11204 .build());
11205 rightWindow->consumeMotionEvent(
11206 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011207 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011208
11209 // Act: pilfer from spy. Spy is currently receiving touch events.
11210 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011211 leftWindow->consumeMotionEvent(
11212 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011213 rightWindow->consumeMotionEvent(
11214 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11215
11216 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11217 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11218 .deviceId(stylusDeviceId)
11219 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11220 .build());
11221 mDispatcher->notifyMotion(
11222 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11223 .deviceId(touchDeviceId)
11224 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11225 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011226 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011227
11228 spy->assertNoEvents();
11229 leftWindow->assertNoEvents();
11230 rightWindow->assertNoEvents();
11231}
11232
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011233TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11234 auto window = createForeground();
11235 auto spy = createSpy();
11236 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11237
11238 mDispatcher->notifyMotion(
11239 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11240 .deviceId(1)
11241 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11242 .build());
11243 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11244 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11245
11246 // Pilfer pointers from the spy window should fail.
11247 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11248 spy->assertNoEvents();
11249 window->assertNoEvents();
11250}
11251
Prabir Pradhand65552b2021-10-07 11:23:50 -070011252class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11253public:
11254 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11255 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11256 std::make_shared<FakeApplicationHandle>();
11257 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011258 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11259 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011260 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011261 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011262 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011263 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011264 overlay->setTrustedOverlay(true);
11265
11266 std::shared_ptr<FakeApplicationHandle> application =
11267 std::make_shared<FakeApplicationHandle>();
11268 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011269 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11270 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011271 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011272 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011273
11274 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011275 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011276 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011277 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011278 return {std::move(overlay), std::move(window)};
11279 }
11280
11281 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011282 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011283 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011284 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011285 }
11286
11287 void sendStylusEvent(int32_t action) {
11288 NotifyMotionArgs motionArgs =
11289 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11290 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011291 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011292 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011293 }
11294};
11295
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011296using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11297
11298TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011299 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011300 ScopedSilentDeath _silentDeath;
11301
Prabir Pradhand65552b2021-10-07 11:23:50 -070011302 auto [overlay, window] = setupStylusOverlayScenario();
11303 overlay->setTrustedOverlay(false);
11304 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011305 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11306 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011307 ".* not a trusted overlay");
11308}
11309
11310TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11311 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011312 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011313
11314 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11315 overlay->consumeMotionDown();
11316 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11317 overlay->consumeMotionUp();
11318
11319 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11320 window->consumeMotionDown();
11321 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11322 window->consumeMotionUp();
11323
11324 overlay->assertNoEvents();
11325 window->assertNoEvents();
11326}
11327
11328TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11329 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011330 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011331 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011332
11333 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11334 overlay->consumeMotionDown();
11335 window->consumeMotionDown();
11336 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11337 overlay->consumeMotionUp();
11338 window->consumeMotionUp();
11339
11340 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11341 window->consumeMotionDown();
11342 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11343 window->consumeMotionUp();
11344
11345 overlay->assertNoEvents();
11346 window->assertNoEvents();
11347}
11348
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011349/**
11350 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11351 * The scenario is as follows:
11352 * - The stylus interceptor overlay is configured as a spy window.
11353 * - The stylus interceptor spy receives the start of a new stylus gesture.
11354 * - It pilfers pointers and then configures itself to no longer be a spy.
11355 * - The stylus interceptor continues to receive the rest of the gesture.
11356 */
11357TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11358 auto [overlay, window] = setupStylusOverlayScenario();
11359 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011360 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011361
11362 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11363 overlay->consumeMotionDown();
11364 window->consumeMotionDown();
11365
11366 // The interceptor pilfers the pointers.
11367 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11368 window->consumeMotionCancel();
11369
11370 // The interceptor configures itself so that it is no longer a spy.
11371 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011372 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011373
11374 // It continues to receive the rest of the stylus gesture.
11375 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11376 overlay->consumeMotionMove();
11377 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11378 overlay->consumeMotionUp();
11379
11380 window->assertNoEvents();
11381}
11382
Prabir Pradhan5735a322022-04-11 17:23:34 +000011383struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011384 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011385 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011386 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11387 std::unique_ptr<InputDispatcher>& mDispatcher;
11388
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011389 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011390 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11391
11392 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011393 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011394 ADISPLAY_ID_DEFAULT, {100, 200},
11395 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11396 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11397 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11398 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11399 }
11400
11401 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011402 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011403 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011404 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011405 mPolicyFlags);
11406 }
11407
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011408 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011409 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11410 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011411 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11412 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011413 window->setOwnerInfo(mPid, mUid);
11414 return window;
11415 }
11416};
11417
11418using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11419
11420TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011421 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011422 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011423 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011424
11425 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11426 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11427 window->consumeMotionDown();
11428
11429 setFocusedWindow(window);
11430 window->consumeFocusEvent(true);
11431
11432 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11433 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11434 window->consumeKeyDown(ADISPLAY_ID_NONE);
11435}
11436
11437TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011438 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011439 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011440 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011441
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011442 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011443 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11444 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11445
11446 setFocusedWindow(window);
11447 window->consumeFocusEvent(true);
11448
11449 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11450 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11451 window->assertNoEvents();
11452}
11453
11454TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011455 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011456 auto window = owner.createWindow("Owned window");
11457 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011458 spy->setSpy(true);
11459 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011460 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011461
11462 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11463 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11464 spy->consumeMotionDown();
11465 window->consumeMotionDown();
11466}
11467
11468TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011469 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011470 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011471
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011472 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011473 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011474 randosSpy->setSpy(true);
11475 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011476 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011477
11478 // The event is targeted at owner's window, so injection should succeed, but the spy should
11479 // not receive the event.
11480 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11481 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11482 randosSpy->assertNoEvents();
11483 window->consumeMotionDown();
11484}
11485
11486TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011487 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011488 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011489
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011490 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011491 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011492 randosSpy->setSpy(true);
11493 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011494 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011495
11496 // A user that has injection permission can inject into any window.
11497 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011498 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011499 ADISPLAY_ID_DEFAULT));
11500 randosSpy->consumeMotionDown();
11501 window->consumeMotionDown();
11502
11503 setFocusedWindow(randosSpy);
11504 randosSpy->consumeFocusEvent(true);
11505
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011506 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011507 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11508 window->assertNoEvents();
11509}
11510
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011511TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011512 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011513 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011514
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011515 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011516 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011517 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11518 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011519 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011520
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011521 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011522 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11523 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11524 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011525 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011526}
11527
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011528using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11529
11530TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11532
11533 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11534 ADISPLAY_ID_DEFAULT);
11535 left->setFrame(Rect(0, 0, 100, 100));
11536 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11537 "Right Window", ADISPLAY_ID_DEFAULT);
11538 right->setFrame(Rect(100, 0, 200, 100));
11539 sp<FakeWindowHandle> spy =
11540 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11541 spy->setFrame(Rect(0, 0, 200, 100));
11542 spy->setTrustedOverlay(true);
11543 spy->setSpy(true);
11544
11545 mDispatcher->onWindowInfosChanged(
11546 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11547
11548 // Hover into the left window.
11549 mDispatcher->notifyMotion(
11550 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11551 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11552 .build());
11553
11554 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11555 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11556
11557 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11558 /*pointerId=*/0));
11559 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11560 /*pointerId=*/0));
11561 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11562 /*pointerId=*/0));
11563
11564 // Hover move to the right window.
11565 mDispatcher->notifyMotion(
11566 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11567 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11568 .build());
11569
11570 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11571 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11572 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11573
11574 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11575 /*pointerId=*/0));
11576 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11577 /*pointerId=*/0));
11578 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11579 /*pointerId=*/0));
11580
11581 // Stop hovering.
11582 mDispatcher->notifyMotion(
11583 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11584 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11585 .build());
11586
11587 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11588 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11589
11590 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11591 /*pointerId=*/0));
11592 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11593 /*pointerId=*/0));
11594 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11595 /*pointerId=*/0));
11596}
11597
11598TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11600
11601 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11602 ADISPLAY_ID_DEFAULT);
11603 left->setFrame(Rect(0, 0, 100, 100));
11604 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11605 "Right Window", ADISPLAY_ID_DEFAULT);
11606 right->setFrame(Rect(100, 0, 200, 100));
11607 sp<FakeWindowHandle> spy =
11608 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11609 spy->setFrame(Rect(0, 0, 200, 100));
11610 spy->setTrustedOverlay(true);
11611 spy->setSpy(true);
11612
11613 mDispatcher->onWindowInfosChanged(
11614 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11615
11616 // First pointer down on left window.
11617 mDispatcher->notifyMotion(
11618 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11619 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11620 .build());
11621
11622 left->consumeMotionDown();
11623 spy->consumeMotionDown();
11624
11625 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11626 /*pointerId=*/0));
11627 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11628 /*pointerId=*/0));
11629 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11630 /*pointerId=*/0));
11631
11632 // Second pointer down on right window.
11633 mDispatcher->notifyMotion(
11634 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11635 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11636 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11637 .build());
11638
11639 left->consumeMotionMove();
11640 right->consumeMotionDown();
11641 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11642
11643 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11644 /*pointerId=*/0));
11645 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11646 /*pointerId=*/0));
11647 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11648 /*pointerId=*/0));
11649 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11650 /*pointerId=*/1));
11651 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11652 /*pointerId=*/1));
11653 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11654 /*pointerId=*/1));
11655
11656 // Second pointer up.
11657 mDispatcher->notifyMotion(
11658 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11659 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11660 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11661 .build());
11662
11663 left->consumeMotionMove();
11664 right->consumeMotionUp();
11665 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11666
11667 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11668 /*pointerId=*/0));
11669 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11670 /*pointerId=*/0));
11671 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11672 /*pointerId=*/0));
11673 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11674 /*pointerId=*/1));
11675 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11676 /*pointerId=*/1));
11677 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11678 /*pointerId=*/1));
11679
11680 // First pointer up.
11681 mDispatcher->notifyMotion(
11682 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11683 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11684 .build());
11685
11686 left->consumeMotionUp();
11687 spy->consumeMotionUp();
11688
11689 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11690 /*pointerId=*/0));
11691 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11692 /*pointerId=*/0));
11693 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11694 /*pointerId=*/0));
11695}
11696
11697TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
11698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11699
11700 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11701 ADISPLAY_ID_DEFAULT);
11702 left->setFrame(Rect(0, 0, 100, 100));
11703 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11704 "Right Window", ADISPLAY_ID_DEFAULT);
11705 right->setFrame(Rect(100, 0, 200, 100));
11706
11707 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
11708
11709 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11710 /*pointerId=*/0));
11711 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11712 /*pointerId=*/0));
11713
11714 // Hover move into the window.
11715 mDispatcher->notifyMotion(
11716 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11717 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
11718 .rawXCursorPosition(50)
11719 .rawYCursorPosition(50)
11720 .deviceId(DEVICE_ID)
11721 .build());
11722
11723 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11724
11725 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11726 /*pointerId=*/0));
11727
11728 // Move the mouse with another device. This cancels the hovering pointer from the first device.
11729 mDispatcher->notifyMotion(
11730 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11731 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
11732 .rawXCursorPosition(51)
11733 .rawYCursorPosition(50)
11734 .deviceId(SECOND_DEVICE_ID)
11735 .build());
11736
11737 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11738 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11739
11740 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
11741 // a HOVER_EXIT from the first device.
11742 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11743 /*pointerId=*/0));
11744 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11745 SECOND_DEVICE_ID,
11746 /*pointerId=*/0));
11747
11748 // Move the mouse outside the window. Document the current behavior, where the window does not
11749 // receive HOVER_EXIT even though the mouse left the window.
11750 mDispatcher->notifyMotion(
11751 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11752 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
11753 .rawXCursorPosition(150)
11754 .rawYCursorPosition(50)
11755 .deviceId(SECOND_DEVICE_ID)
11756 .build());
11757
11758 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11759 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11760 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11761 /*pointerId=*/0));
11762 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
11763 SECOND_DEVICE_ID,
11764 /*pointerId=*/0));
11765}
11766
Garfield Tane84e6f92019-08-29 17:28:41 -070011767} // namespace android::inputdispatcher